1 /*
2 * SRT - Secure, Reliable, Transport
3 * Copyright (c) 2018 Haivision Systems Inc.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 */
10
11
12 /*****************************************************************************
13 written by
14 Haivision Systems Inc.
15
16 2011-06-23 (jdube)
17 HaiCrypt initial implementation.
18 2014-03-11 (jdube)
19 Adaptation for SRT.
20 *****************************************************************************/
21
22 #include <string.h> /* memcpy */
23 #include "hcrypt.h"
24
hcryptCtx_Rx_Init(hcrypt_Session * crypto,hcrypt_Ctx * ctx,const HaiCrypt_Cfg * cfg)25 int hcryptCtx_Rx_Init(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const HaiCrypt_Cfg *cfg)
26 {
27 ctx->mode = HCRYPT_CTX_MODE_AESCTR;
28 ctx->status = HCRYPT_CTX_S_INIT;
29
30 ctx->msg_info = crypto->msg_info;
31
32 if (cfg && hcryptCtx_SetSecret(crypto, ctx, &cfg->secret)) {
33 return(-1);
34 }
35 ctx->status = HCRYPT_CTX_S_SARDY;
36 return(0);
37 }
38
hcryptCtx_Rx_Rekey(hcrypt_Session * crypto,hcrypt_Ctx * ctx,unsigned char * sek,size_t sek_len)39 int hcryptCtx_Rx_Rekey(hcrypt_Session *crypto, hcrypt_Ctx *ctx, unsigned char *sek, size_t sek_len)
40 {
41 if (crypto->cryspr->ms_setkey(crypto->cryspr_cb, ctx, sek, sek_len)) {
42 HCRYPT_LOG(LOG_ERR, "cryspr setkey[%d](sek) failed\n", hcryptCtx_GetKeyIndex(ctx));
43 return(-1);
44 }
45 memcpy(ctx->sek, sek, sek_len);
46 ctx->sek_len = sek_len;
47
48 HCRYPT_LOG(LOG_INFO, "updated context[%d]\n", hcryptCtx_GetKeyIndex(ctx));
49 HCRYPT_PRINTKEY(ctx->sek, ctx->sek_len, "sek");
50 ctx->status = HCRYPT_CTX_S_KEYED;
51 return(0);
52 }
53
54 /* Parse Keying Material message */
hcryptCtx_Rx_ParseKM(hcrypt_Session * crypto,unsigned char * km_msg,size_t msg_len)55 int hcryptCtx_Rx_ParseKM(hcrypt_Session *crypto, unsigned char *km_msg, size_t msg_len)
56 {
57 size_t sek_len, salt_len;
58 unsigned char seks[HAICRYPT_KEY_MAX_SZ * 2];
59 int sek_cnt;
60 size_t kek_len = 0;
61 hcrypt_Ctx *ctx;
62 int do_pbkdf = 0;
63
64 if (NULL == crypto) {
65 HCRYPT_LOG(LOG_ERR, "Rx_ParseKM: invalid params: crypto=%p\n", crypto);
66 return(-1);
67 }
68
69 /* Validate message content */
70 {
71 if (msg_len <= HCRYPT_MSG_KM_OFS_SALT) {
72 HCRYPT_LOG(LOG_WARNING, "KMmsg length too small (%zd)\n", msg_len);
73 return(-1);
74 }
75 salt_len = hcryptMsg_KM_GetSaltLen(km_msg);
76 sek_len = hcryptMsg_KM_GetSekLen(km_msg);
77
78 if ((salt_len > HAICRYPT_SALT_SZ)
79 || (sek_len > HAICRYPT_KEY_MAX_SZ)) {
80 HCRYPT_LOG(LOG_WARNING, "%s", "KMmsg unsupported salt/key length\n");
81 return(-1);
82 }
83 if ((16 != sek_len)
84 && (24 != sek_len)
85 && (32 != sek_len)) {
86 HCRYPT_LOG(LOG_WARNING, "%s", "KMmsg unsupported key length\n");
87 return(-1);
88 }
89 if (hcryptMsg_KM_HasBothSek(km_msg)) {
90 sek_cnt = 2;
91 } else {
92 sek_cnt = 1;
93 }
94 if (msg_len != (HCRYPT_MSG_KM_OFS_SALT + salt_len + (sek_cnt * sek_len) + HAICRYPT_WRAPKEY_SIGN_SZ)) {
95 HCRYPT_LOG(LOG_WARNING, "KMmsg length inconsistent (%zd,%zd,%zd)\n",
96 salt_len, sek_len, msg_len);
97 return(-1);
98 }
99
100 /* Check options support */
101 if ((HCRYPT_CIPHER_AES_CTR != km_msg[HCRYPT_MSG_KM_OFS_CIPHER])
102 || (HCRYPT_AUTH_NONE != km_msg[HCRYPT_MSG_KM_OFS_AUTH])) {
103 HCRYPT_LOG(LOG_WARNING, "%s", "KMmsg unsupported option\n");
104 return(-1);
105 }
106
107 if (crypto->se != km_msg[HCRYPT_MSG_KM_OFS_SE]) {
108 HCRYPT_LOG(LOG_WARNING, "%s", "KMmsg invalid SE\n");
109 return(-1);
110 }
111
112 /* Check KEKI here and pick right key */
113 //>>todo
114 /*
115 * We support no key exchange,
116 * KEK is preshared or derived from a passphrase
117 */
118 }
119
120 /* Pick the context updated by this KMmsg */
121 if (hcryptMsg_KM_HasBothSek(km_msg) && (NULL != crypto->ctx)) {
122 ctx = crypto->ctx->alt; /* 2 SEK KM, start with inactive ctx */
123 } else {
124 ctx = &crypto->ctx_pair[hcryptMsg_KM_GetKeyIndex(km_msg)];
125 }
126 if (NULL == ctx) {
127 HCRYPT_LOG(LOG_WARNING, "%s", "KMmsg invalid flags (no SEK)\n");
128 return(-1);
129 }
130
131 /* Check Salt and get if new */
132 if ((salt_len != ctx->salt_len)
133 || (0 != memcmp(ctx->salt, &km_msg[HCRYPT_MSG_KM_OFS_SALT], salt_len))) {
134 /* Salt changed (or 1st KMmsg received) */
135 memcpy(ctx->salt, &km_msg[HCRYPT_MSG_KM_OFS_SALT], salt_len);
136 ctx->salt_len = salt_len;
137 do_pbkdf = 1; /* Impact on password derived kek */
138 }
139
140 /* Check SEK length and get if new */
141 if (sek_len != ctx->sek_len) {
142 /* Key length changed or 1st KMmsg received */
143 ctx->sek_len = sek_len;
144 do_pbkdf = 1; /* Impact on password derived kek */
145 }
146
147 /*
148 * Regenerate KEK if it is password derived
149 * and Salt or SEK length changed
150 */
151 if (ctx->cfg.pwd_len && do_pbkdf) {
152 if (hcryptCtx_GenSecret(crypto, ctx)) {
153 return(-1);
154 }
155 ctx->status = HCRYPT_CTX_S_SARDY;
156 kek_len = sek_len; /* KEK changed */
157 }
158
159 /* Unwrap SEK(s) and set in context */
160 if (0 > crypto->cryspr->km_unwrap(crypto->cryspr_cb, seks,
161 &km_msg[HCRYPT_MSG_KM_OFS_SALT + salt_len],
162 (sek_cnt * sek_len) + HAICRYPT_WRAPKEY_SIGN_SZ)) {
163 HCRYPT_LOG(LOG_WARNING, "%s", "unwrap key failed\n");
164 return(-2); //Report unmatched shared secret
165 }
166 /*
167 * First SEK in KMmsg is eSEK if both SEK present
168 */
169 hcryptCtx_Rx_Rekey(crypto, ctx,
170 ((2 == sek_cnt) && (ctx->flags & HCRYPT_MSG_F_oSEK)) ? &seks[sek_len] : &seks[0],
171 sek_len);
172
173 /*
174 * Refresh KMmsg cache to detect Keying Material changes
175 */
176 ctx->KMmsg_len = msg_len;
177 memcpy(ctx->KMmsg_cache, km_msg, msg_len);
178
179 /* update other (alternate) context if both SEK provided */
180 if (2 == sek_cnt) {
181 hcrypt_Ctx *alt = ctx->alt;
182
183 memcpy(alt->salt, &km_msg[HCRYPT_MSG_KM_OFS_SALT], salt_len);
184 alt->salt_len = salt_len;
185
186 if (kek_len) { /* New or changed KEK */
187 // memcpy(&alt->aes_kek, &ctx->aes_kek, sizeof(alt->aes_kek));
188 alt->status = HCRYPT_CTX_S_SARDY;
189 }
190
191 hcryptCtx_Rx_Rekey(crypto, alt,
192 ((2 == sek_cnt) && (alt->flags & HCRYPT_MSG_F_oSEK)) ? &seks[sek_len] : &seks[0],
193 sek_len);
194
195 alt->KMmsg_len = msg_len;
196 memcpy(alt->KMmsg_cache, km_msg, msg_len);
197 }
198 return(0);
199 }
200