hcrypt_ctx_rx.c 6.5 KB

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