diff --git a/keyserver/src/creators/olm-session-creator.js b/keyserver/src/creators/olm-session-creator.js new file mode 100644 --- /dev/null +++ b/keyserver/src/creators/olm-session-creator.js @@ -0,0 +1,40 @@ +// @flow + +import { ServerError } from 'lib/utils/errors.js'; + +import { dbQuery, SQL } from '../database/database.js'; +import { fetchOlmAccount } from '../updaters/olm-account-updater.js'; +import { createPickledOlmSession } from '../utils/olm-utils.js'; + +async function createOlmSession( + initialEncryptedMessage: string, + olmSessionType: 'content' | 'notifications', + cookieID: string, +): Promise { + const { account, picklingKey } = await fetchOlmAccount(olmSessionType); + let pickledOlmSession; + try { + pickledOlmSession = await createPickledOlmSession( + account, + picklingKey, + initialEncryptedMessage, + ); + } catch (e) { + throw new ServerError('olm_session_creation_failure'); + } + + const isContent = olmSessionType === 'content'; + // We match the native client behavior here where olm session is overwritten + // in case it is initialized twice for the same pair of identities + await dbQuery( + SQL` + INSERT INTO olm_sessions (cookie_id, is_content, + version, pickled_olm_session) + VALUES (${cookieID}, ${isContent}, 0, ${pickledOlmSession}) + ON DUPLICATE KEY UPDATE + pickled_olm_session = ${pickledOlmSession} + `, + ); +} + +export { createOlmSession }; diff --git a/keyserver/src/utils/olm-utils.js b/keyserver/src/utils/olm-utils.js --- a/keyserver/src/utils/olm-utils.js +++ b/keyserver/src/utils/olm-utils.js @@ -4,6 +4,7 @@ import type { Account as OlmAccount, Utility as OlmUtility, + Session as OlmSession, } from '@commapp/olm'; import uuid from 'uuid'; @@ -42,6 +43,28 @@ return account; } +async function createPickledOlmSession( + account: OlmAccount, + accountPicklingKey: string, + initialEncryptedMessage: string, +): Promise { + await olm.init(); + const session = new olm.Session(); + session.create_inbound(account, initialEncryptedMessage); + session.decrypt(0, initialEncryptedMessage); + return session.pickle(accountPicklingKey); +} + +async function unpickleOlmSession( + pickledSession: string, + picklingKey: string, +): Promise { + await olm.init(); + const session = new olm.Session(); + session.unpickle(picklingKey, pickledSession); + return session; +} + let cachedOLMUtility: OlmUtility; function getOlmUtility(): OlmUtility { if (cachedOLMUtility) { @@ -84,7 +107,9 @@ export { createPickledOlmAccount, + createPickledOlmSession, getOlmUtility, unpickleOlmAccount, + unpickleOlmSession, validateAccountPrekey, };