2
0

cmp_protect.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /*
  2. * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
  3. * Copyright Nokia 2007-2019
  4. * Copyright Siemens AG 2015-2019
  5. *
  6. * Licensed under the Apache License 2.0 (the "License"). You may not use
  7. * this file except in compliance with the License. You can obtain a copy
  8. * in the file LICENSE in the source distribution or at
  9. * https://www.openssl.org/source/license.html
  10. */
  11. #include "cmp_local.h"
  12. #include "crypto/asn1.h"
  13. /* explicit #includes not strictly needed since implied by the above: */
  14. #include <openssl/asn1t.h>
  15. #include <openssl/cmp.h>
  16. #include <openssl/crmf.h>
  17. #include <openssl/err.h>
  18. #include <openssl/x509.h>
  19. /*
  20. * This function is also used by the internal verify_PBMAC() in cmp_vfy.c.
  21. *
  22. * Calculate protection for |msg| according to |msg->header->protectionAlg|
  23. * using the credentials, library context, and property criteria in the ctx.
  24. * Unless |msg->header->protectionAlg| is PasswordBasedMAC,
  25. * its value is completed according to |ctx->pkey| and |ctx->digest|,
  26. * where the latter irrelevant in the case of Edwards curves.
  27. *
  28. * returns ASN1_BIT_STRING representing the protection on success, else NULL
  29. */
  30. ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
  31. const OSSL_CMP_MSG *msg)
  32. {
  33. ASN1_BIT_STRING *prot = NULL;
  34. OSSL_CMP_PROTECTEDPART prot_part;
  35. const ASN1_OBJECT *algorOID = NULL;
  36. const void *ppval = NULL;
  37. int pptype = 0;
  38. if (!ossl_assert(ctx != NULL && msg != NULL))
  39. return NULL;
  40. /* construct data to be signed */
  41. prot_part.header = msg->header;
  42. prot_part.body = msg->body;
  43. if (msg->header->protectionAlg == NULL) {
  44. ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_ALGORITHM_ID);
  45. return NULL;
  46. }
  47. X509_ALGOR_get0(&algorOID, &pptype, &ppval, msg->header->protectionAlg);
  48. if (OBJ_obj2nid(algorOID) == NID_id_PasswordBasedMAC) {
  49. int len;
  50. size_t prot_part_der_len;
  51. unsigned char *prot_part_der = NULL;
  52. size_t sig_len;
  53. unsigned char *protection = NULL;
  54. OSSL_CRMF_PBMPARAMETER *pbm = NULL;
  55. ASN1_STRING *pbm_str = NULL;
  56. const unsigned char *pbm_str_uc = NULL;
  57. if (ctx->secretValue == NULL) {
  58. ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PBM_SECRET);
  59. return NULL;
  60. }
  61. if (ppval == NULL) {
  62. ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CALCULATING_PROTECTION);
  63. return NULL;
  64. }
  65. len = i2d_OSSL_CMP_PROTECTEDPART(&prot_part, &prot_part_der);
  66. if (len < 0 || prot_part_der == NULL) {
  67. ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CALCULATING_PROTECTION);
  68. goto end;
  69. }
  70. prot_part_der_len = (size_t)len;
  71. pbm_str = (ASN1_STRING *)ppval;
  72. pbm_str_uc = pbm_str->data;
  73. pbm = d2i_OSSL_CRMF_PBMPARAMETER(NULL, &pbm_str_uc, pbm_str->length);
  74. if (pbm == NULL) {
  75. ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_ALGORITHM_OID);
  76. goto end;
  77. }
  78. if (!OSSL_CRMF_pbm_new(ctx->libctx, ctx->propq,
  79. pbm, prot_part_der, prot_part_der_len,
  80. ctx->secretValue->data, ctx->secretValue->length,
  81. &protection, &sig_len))
  82. goto end;
  83. if ((prot = ASN1_BIT_STRING_new()) == NULL)
  84. goto end;
  85. /* OpenSSL by default encodes all bit strings as ASN.1 NamedBitList */
  86. ossl_asn1_string_set_bits_left(prot, 0);
  87. if (!ASN1_BIT_STRING_set(prot, protection, sig_len)) {
  88. ASN1_BIT_STRING_free(prot);
  89. prot = NULL;
  90. }
  91. end:
  92. OSSL_CRMF_PBMPARAMETER_free(pbm);
  93. OPENSSL_free(protection);
  94. OPENSSL_free(prot_part_der);
  95. return prot;
  96. } else {
  97. const EVP_MD *md = ctx->digest;
  98. char name[80] = "";
  99. if (ctx->pkey == NULL) {
  100. ERR_raise(ERR_LIB_CMP,
  101. CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION);
  102. return NULL;
  103. }
  104. if (EVP_PKEY_get_default_digest_name(ctx->pkey, name, sizeof(name)) > 0
  105. && strcmp(name, "UNDEF") == 0) /* at least for Ed25519, Ed448 */
  106. md = NULL;
  107. if ((prot = ASN1_BIT_STRING_new()) == NULL)
  108. return NULL;
  109. if (ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CMP_PROTECTEDPART),
  110. msg->header->protectionAlg, /* sets X509_ALGOR */
  111. NULL, prot, &prot_part, NULL, ctx->pkey, md,
  112. ctx->libctx, ctx->propq))
  113. return prot;
  114. ASN1_BIT_STRING_free(prot);
  115. return NULL;
  116. }
  117. }
  118. /* ctx is not const just because ctx->chain may get adapted */
  119. int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
  120. {
  121. if (!ossl_assert(ctx != NULL && msg != NULL))
  122. return 0;
  123. /* Add first ctx->cert and its chain if using signature-based protection */
  124. if (!ctx->unprotectedSend && ctx->secretValue == NULL
  125. && ctx->cert != NULL && ctx->pkey != NULL) {
  126. int prepend = X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
  127. | X509_ADD_FLAG_PREPEND | X509_ADD_FLAG_NO_SS;
  128. /* if not yet done try to build chain using available untrusted certs */
  129. if (ctx->chain == NULL) {
  130. ossl_cmp_debug(ctx,
  131. "trying to build chain for own CMP signer cert");
  132. ctx->chain = X509_build_chain(ctx->cert, ctx->untrusted, NULL, 0,
  133. ctx->libctx, ctx->propq);
  134. if (ctx->chain != NULL) {
  135. ossl_cmp_debug(ctx,
  136. "success building chain for own CMP signer cert");
  137. } else {
  138. /* dump errors to avoid confusion when printing further ones */
  139. OSSL_CMP_CTX_print_errors(ctx);
  140. ossl_cmp_warn(ctx,
  141. "could not build chain for own CMP signer cert");
  142. }
  143. }
  144. if (ctx->chain != NULL) {
  145. if (!ossl_x509_add_certs_new(&msg->extraCerts, ctx->chain, prepend))
  146. return 0;
  147. } else {
  148. /* make sure that at least our own signer cert is included first */
  149. if (!ossl_x509_add_cert_new(&msg->extraCerts, ctx->cert, prepend))
  150. return 0;
  151. ossl_cmp_debug(ctx, "fallback: adding just own CMP signer cert");
  152. }
  153. }
  154. /* add any additional certificates from ctx->extraCertsOut */
  155. if (!ossl_x509_add_certs_new(&msg->extraCerts, ctx->extraCertsOut,
  156. X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
  157. return 0;
  158. /* in case extraCerts are empty list avoid empty ASN.1 sequence */
  159. if (sk_X509_num(msg->extraCerts) == 0) {
  160. sk_X509_free(msg->extraCerts);
  161. msg->extraCerts = NULL;
  162. }
  163. return 1;
  164. }
  165. /*
  166. * Create an X509_ALGOR structure for PasswordBasedMAC protection based on
  167. * the pbm settings in the context
  168. */
  169. static X509_ALGOR *pbmac_algor(const OSSL_CMP_CTX *ctx)
  170. {
  171. OSSL_CRMF_PBMPARAMETER *pbm = NULL;
  172. unsigned char *pbm_der = NULL;
  173. int pbm_der_len;
  174. ASN1_STRING *pbm_str = NULL;
  175. X509_ALGOR *alg = NULL;
  176. if (!ossl_assert(ctx != NULL))
  177. return NULL;
  178. pbm = OSSL_CRMF_pbmp_new(ctx->libctx, ctx->pbm_slen,
  179. EVP_MD_get_type(ctx->pbm_owf), ctx->pbm_itercnt,
  180. ctx->pbm_mac);
  181. pbm_str = ASN1_STRING_new();
  182. if (pbm == NULL || pbm_str == NULL)
  183. goto err;
  184. if ((pbm_der_len = i2d_OSSL_CRMF_PBMPARAMETER(pbm, &pbm_der)) < 0)
  185. goto err;
  186. if (!ASN1_STRING_set(pbm_str, pbm_der, pbm_der_len))
  187. goto err;
  188. alg = ossl_X509_ALGOR_from_nid(NID_id_PasswordBasedMAC,
  189. V_ASN1_SEQUENCE, pbm_str);
  190. err:
  191. if (alg == NULL)
  192. ASN1_STRING_free(pbm_str);
  193. OPENSSL_free(pbm_der);
  194. OSSL_CRMF_PBMPARAMETER_free(pbm);
  195. return alg;
  196. }
  197. static int set_senderKID(const OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg,
  198. const ASN1_OCTET_STRING *id)
  199. {
  200. if (id == NULL)
  201. id = ctx->referenceValue; /* standard for PBM, fallback for sig-based */
  202. return id == NULL || ossl_cmp_hdr_set1_senderKID(msg->header, id);
  203. }
  204. /* ctx is not const just because ctx->chain may get adapted */
  205. int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
  206. {
  207. if (!ossl_assert(ctx != NULL && msg != NULL))
  208. return 0;
  209. /*
  210. * For the case of re-protection remove pre-existing protection.
  211. * Does not remove any pre-existing extraCerts.
  212. */
  213. X509_ALGOR_free(msg->header->protectionAlg);
  214. msg->header->protectionAlg = NULL;
  215. ASN1_BIT_STRING_free(msg->protection);
  216. msg->protection = NULL;
  217. if (ctx->unprotectedSend) {
  218. if (!set_senderKID(ctx, msg, NULL))
  219. goto err;
  220. } else if (ctx->secretValue != NULL) {
  221. /* use PasswordBasedMac according to 5.1.3.1 if secretValue is given */
  222. if ((msg->header->protectionAlg = pbmac_algor(ctx)) == NULL)
  223. goto err;
  224. if (!set_senderKID(ctx, msg, NULL))
  225. goto err;
  226. /*
  227. * will add any additional certificates from ctx->extraCertsOut
  228. * while not needed to validate the protection certificate,
  229. * the option to do this might be handy for certain use cases
  230. */
  231. } else if (ctx->cert != NULL && ctx->pkey != NULL) {
  232. /* use MSG_SIG_ALG according to 5.1.3.3 if client cert and key given */
  233. /* make sure that key and certificate match */
  234. if (!X509_check_private_key(ctx->cert, ctx->pkey)) {
  235. ERR_raise(ERR_LIB_CMP, CMP_R_CERT_AND_KEY_DO_NOT_MATCH);
  236. goto err;
  237. }
  238. if ((msg->header->protectionAlg = X509_ALGOR_new()) == NULL)
  239. goto err;
  240. /* set senderKID to keyIdentifier of the cert according to 5.1.1 */
  241. if (!set_senderKID(ctx, msg, X509_get0_subject_key_id(ctx->cert)))
  242. goto err;
  243. /*
  244. * will add ctx->cert followed, if possible, by its chain built
  245. * from ctx->untrusted, and then ctx->extraCertsOut
  246. */
  247. } else {
  248. ERR_raise(ERR_LIB_CMP,
  249. CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION);
  250. goto err;
  251. }
  252. if (!ctx->unprotectedSend
  253. /* protect according to msg->header->protectionAlg partly set above */
  254. && ((msg->protection = ossl_cmp_calc_protection(ctx, msg)) == NULL))
  255. goto err;
  256. /*
  257. * For signature-based protection add ctx->cert followed by its chain.
  258. * Finally add any additional certificates from ctx->extraCertsOut;
  259. * even if not needed to validate the protection
  260. * the option to do this might be handy for certain use cases.
  261. */
  262. if (!ossl_cmp_msg_add_extraCerts(ctx, msg))
  263. goto err;
  264. /*
  265. * As required by RFC 4210 section 5.1.1., if the sender name is not known
  266. * to the client it set to NULL-DN. In this case for identification at least
  267. * the senderKID must be set, where we took the referenceValue as fallback.
  268. */
  269. if (!(ossl_cmp_general_name_is_NULL_DN(msg->header->sender)
  270. && msg->header->senderKID == NULL))
  271. return 1;
  272. ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_SENDER_IDENTIFICATION);
  273. err:
  274. ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROTECTING_MESSAGE);
  275. return 0;
  276. }