cms_enc.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include "internal/cryptlib.h"
  10. #include <openssl/asn1t.h>
  11. #include <openssl/pem.h>
  12. #include <openssl/x509v3.h>
  13. #include <openssl/err.h>
  14. #include <openssl/cms.h>
  15. #include <openssl/rand.h>
  16. #include "cms_lcl.h"
  17. /* CMS EncryptedData Utilities */
  18. /* Return BIO based on EncryptedContentInfo and key */
  19. BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
  20. {
  21. BIO *b;
  22. EVP_CIPHER_CTX *ctx;
  23. const EVP_CIPHER *ciph;
  24. X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
  25. unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
  26. unsigned char *tkey = NULL;
  27. size_t tkeylen = 0;
  28. int ok = 0;
  29. int enc, keep_key = 0;
  30. enc = ec->cipher ? 1 : 0;
  31. b = BIO_new(BIO_f_cipher());
  32. if (b == NULL) {
  33. CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
  34. return NULL;
  35. }
  36. BIO_get_cipher_ctx(b, &ctx);
  37. if (enc) {
  38. ciph = ec->cipher;
  39. /*
  40. * If not keeping key set cipher to NULL so subsequent calls decrypt.
  41. */
  42. if (ec->key)
  43. ec->cipher = NULL;
  44. } else {
  45. ciph = EVP_get_cipherbyobj(calg->algorithm);
  46. if (!ciph) {
  47. CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER);
  48. goto err;
  49. }
  50. }
  51. if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) {
  52. CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
  53. CMS_R_CIPHER_INITIALISATION_ERROR);
  54. goto err;
  55. }
  56. if (enc) {
  57. int ivlen;
  58. calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
  59. /* Generate a random IV if we need one */
  60. ivlen = EVP_CIPHER_CTX_iv_length(ctx);
  61. if (ivlen > 0) {
  62. if (RAND_bytes(iv, ivlen) <= 0)
  63. goto err;
  64. piv = iv;
  65. }
  66. } else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) {
  67. CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
  68. CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
  69. goto err;
  70. }
  71. tkeylen = EVP_CIPHER_CTX_key_length(ctx);
  72. /* Generate random session key */
  73. if (!enc || !ec->key) {
  74. tkey = OPENSSL_malloc(tkeylen);
  75. if (tkey == NULL) {
  76. CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
  77. goto err;
  78. }
  79. if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0)
  80. goto err;
  81. }
  82. if (!ec->key) {
  83. ec->key = tkey;
  84. ec->keylen = tkeylen;
  85. tkey = NULL;
  86. if (enc)
  87. keep_key = 1;
  88. else
  89. ERR_clear_error();
  90. }
  91. if (ec->keylen != tkeylen) {
  92. /* If necessary set key length */
  93. if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) {
  94. /*
  95. * Only reveal failure if debugging so we don't leak information
  96. * which may be useful in MMA.
  97. */
  98. if (enc || ec->debug) {
  99. CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
  100. CMS_R_INVALID_KEY_LENGTH);
  101. goto err;
  102. } else {
  103. /* Use random key */
  104. OPENSSL_clear_free(ec->key, ec->keylen);
  105. ec->key = tkey;
  106. ec->keylen = tkeylen;
  107. tkey = NULL;
  108. ERR_clear_error();
  109. }
  110. }
  111. }
  112. if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) {
  113. CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
  114. CMS_R_CIPHER_INITIALISATION_ERROR);
  115. goto err;
  116. }
  117. if (enc) {
  118. calg->parameter = ASN1_TYPE_new();
  119. if (calg->parameter == NULL) {
  120. CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
  121. goto err;
  122. }
  123. if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) {
  124. CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
  125. CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
  126. goto err;
  127. }
  128. /* If parameter type not set omit parameter */
  129. if (calg->parameter->type == V_ASN1_UNDEF) {
  130. ASN1_TYPE_free(calg->parameter);
  131. calg->parameter = NULL;
  132. }
  133. }
  134. ok = 1;
  135. err:
  136. if (!keep_key || !ok) {
  137. OPENSSL_clear_free(ec->key, ec->keylen);
  138. ec->key = NULL;
  139. }
  140. OPENSSL_clear_free(tkey, tkeylen);
  141. if (ok)
  142. return b;
  143. BIO_free(b);
  144. return NULL;
  145. }
  146. int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
  147. const EVP_CIPHER *cipher,
  148. const unsigned char *key, size_t keylen)
  149. {
  150. ec->cipher = cipher;
  151. if (key) {
  152. if ((ec->key = OPENSSL_malloc(keylen)) == NULL) {
  153. CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT, ERR_R_MALLOC_FAILURE);
  154. return 0;
  155. }
  156. memcpy(ec->key, key, keylen);
  157. }
  158. ec->keylen = keylen;
  159. if (cipher)
  160. ec->contentType = OBJ_nid2obj(NID_pkcs7_data);
  161. return 1;
  162. }
  163. int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
  164. const unsigned char *key, size_t keylen)
  165. {
  166. CMS_EncryptedContentInfo *ec;
  167. if (!key || !keylen) {
  168. CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY);
  169. return 0;
  170. }
  171. if (ciph) {
  172. cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData);
  173. if (!cms->d.encryptedData) {
  174. CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, ERR_R_MALLOC_FAILURE);
  175. return 0;
  176. }
  177. cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted);
  178. cms->d.encryptedData->version = 0;
  179. } else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) {
  180. CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NOT_ENCRYPTED_DATA);
  181. return 0;
  182. }
  183. ec = cms->d.encryptedData->encryptedContentInfo;
  184. return cms_EncryptedContent_init(ec, ciph, key, keylen);
  185. }
  186. BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms)
  187. {
  188. CMS_EncryptedData *enc = cms->d.encryptedData;
  189. if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
  190. enc->version = 2;
  191. return cms_EncryptedContent_init_bio(enc->encryptedContentInfo);
  192. }