diff options
Diffstat (limited to 'src/lib/libcrypto/cms/cms_pwri.c')
-rw-r--r-- | src/lib/libcrypto/cms/cms_pwri.c | 90 |
1 files changed, 42 insertions, 48 deletions
diff --git a/src/lib/libcrypto/cms/cms_pwri.c b/src/lib/libcrypto/cms/cms_pwri.c index d7f5697ff0..af237be98f 100644 --- a/src/lib/libcrypto/cms/cms_pwri.c +++ b/src/lib/libcrypto/cms/cms_pwri.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: cms_pwri.c,v 1.16 2019/08/10 16:42:20 jsing Exp $ */ | 1 | /* $OpenBSD: cms_pwri.c,v 1.17 2019/08/10 18:15:52 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
4 | * project. | 4 | * project. |
@@ -63,10 +63,12 @@ | |||
63 | #include "cms_lcl.h" | 63 | #include "cms_lcl.h" |
64 | #include "asn1/asn1_locl.h" | 64 | #include "asn1/asn1_locl.h" |
65 | 65 | ||
66 | int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, | 66 | int |
67 | unsigned char *pass, ossl_ssize_t passlen) | 67 | CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, unsigned char *pass, |
68 | ossl_ssize_t passlen) | ||
68 | { | 69 | { |
69 | CMS_PasswordRecipientInfo *pwri; | 70 | CMS_PasswordRecipientInfo *pwri; |
71 | |||
70 | if (ri->type != CMS_RECIPINFO_PASS) { | 72 | if (ri->type != CMS_RECIPINFO_PASS) { |
71 | CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI); | 73 | CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI); |
72 | return 0; | 74 | return 0; |
@@ -77,15 +79,14 @@ int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, | |||
77 | if (pass && passlen < 0) | 79 | if (pass && passlen < 0) |
78 | passlen = strlen((char *)pass); | 80 | passlen = strlen((char *)pass); |
79 | pwri->passlen = passlen; | 81 | pwri->passlen = passlen; |
82 | |||
80 | return 1; | 83 | return 1; |
81 | } | 84 | } |
82 | 85 | ||
83 | CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, | 86 | CMS_RecipientInfo * |
84 | int iter, int wrap_nid, | 87 | CMS_add0_recipient_password(CMS_ContentInfo *cms, int iter, int wrap_nid, |
85 | int pbe_nid, | 88 | int pbe_nid, unsigned char *pass, ossl_ssize_t passlen, |
86 | unsigned char *pass, | 89 | const EVP_CIPHER *kekciph) |
87 | ossl_ssize_t passlen, | ||
88 | const EVP_CIPHER *kekciph) | ||
89 | { | 90 | { |
90 | CMS_RecipientInfo *ri = NULL; | 91 | CMS_RecipientInfo *ri = NULL; |
91 | CMS_EnvelopedData *env; | 92 | CMS_EnvelopedData *env; |
@@ -115,7 +116,7 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, | |||
115 | } | 116 | } |
116 | if (wrap_nid != NID_id_alg_PWRI_KEK) { | 117 | if (wrap_nid != NID_id_alg_PWRI_KEK) { |
117 | CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, | 118 | CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, |
118 | CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); | 119 | CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); |
119 | return NULL; | 120 | return NULL; |
120 | } | 121 | } |
121 | 122 | ||
@@ -147,7 +148,7 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, | |||
147 | } | 148 | } |
148 | if (EVP_CIPHER_param_to_asn1(ctx, encalg->parameter) <= 0) { | 149 | if (EVP_CIPHER_param_to_asn1(ctx, encalg->parameter) <= 0) { |
149 | CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, | 150 | CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, |
150 | CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); | 151 | CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); |
151 | goto err; | 152 | goto err; |
152 | } | 153 | } |
153 | } | 154 | } |
@@ -179,8 +180,7 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, | |||
179 | goto merr; | 180 | goto merr; |
180 | 181 | ||
181 | if (!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR), | 182 | if (!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR), |
182 | &pwri->keyEncryptionAlgorithm->parameter-> | 183 | &pwri->keyEncryptionAlgorithm->parameter->value.sequence)) |
183 | value.sequence)) | ||
184 | goto merr; | 184 | goto merr; |
185 | pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE; | 185 | pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE; |
186 | 186 | ||
@@ -209,8 +209,8 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, | |||
209 | if (ri) | 209 | if (ri) |
210 | M_ASN1_free_of(ri, CMS_RecipientInfo); | 210 | M_ASN1_free_of(ri, CMS_RecipientInfo); |
211 | X509_ALGOR_free(encalg); | 211 | X509_ALGOR_free(encalg); |
212 | return NULL; | ||
213 | 212 | ||
213 | return NULL; | ||
214 | } | 214 | } |
215 | 215 | ||
216 | /* | 216 | /* |
@@ -218,13 +218,14 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, | |||
218 | * some point this should go into EVP. | 218 | * some point this should go into EVP. |
219 | */ | 219 | */ |
220 | 220 | ||
221 | static int kek_unwrap_key(unsigned char *out, size_t *outlen, | 221 | static int |
222 | const unsigned char *in, size_t inlen, | 222 | kek_unwrap_key(unsigned char *out, size_t *outlen, const unsigned char *in, |
223 | EVP_CIPHER_CTX *ctx) | 223 | size_t inlen, EVP_CIPHER_CTX *ctx) |
224 | { | 224 | { |
225 | size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); | 225 | size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); |
226 | unsigned char *tmp; | 226 | unsigned char *tmp; |
227 | int outl, rv = 0; | 227 | int outl, rv = 0; |
228 | |||
228 | if (inlen < 2 * blocklen) { | 229 | if (inlen < 2 * blocklen) { |
229 | /* too small */ | 230 | /* too small */ |
230 | return 0; | 231 | return 0; |
@@ -237,16 +238,16 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen, | |||
237 | CMSerr(CMS_F_KEK_UNWRAP_KEY, ERR_R_MALLOC_FAILURE); | 238 | CMSerr(CMS_F_KEK_UNWRAP_KEY, ERR_R_MALLOC_FAILURE); |
238 | return 0; | 239 | return 0; |
239 | } | 240 | } |
241 | |||
240 | /* setup IV by decrypting last two blocks */ | 242 | /* setup IV by decrypting last two blocks */ |
241 | if (!EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl, | 243 | if (!EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl, |
242 | in + inlen - 2 * blocklen, blocklen * 2) | 244 | in + inlen - 2 * blocklen, blocklen * 2) |
243 | /* | 245 | /* |
244 | * Do a decrypt of last decrypted block to set IV to correct value | 246 | * Do a decrypt of last decrypted block to set IV to correct value |
245 | * output it to start of buffer so we don't corrupt decrypted block | 247 | * output it to start of buffer so we don't corrupt decrypted block |
246 | * this works because buffer is at least two block lengths long. | 248 | * this works because buffer is at least two block lengths long. |
247 | */ | 249 | */ |
248 | || !EVP_DecryptUpdate(ctx, tmp, &outl, | 250 | || !EVP_DecryptUpdate(ctx, tmp, &outl, tmp + inlen - blocklen, blocklen) |
249 | tmp + inlen - blocklen, blocklen) | ||
250 | /* Can now decrypt first n - 1 blocks */ | 251 | /* Can now decrypt first n - 1 blocks */ |
251 | || !EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen) | 252 | || !EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen) |
252 | 253 | ||
@@ -267,19 +268,21 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen, | |||
267 | *outlen = (size_t)tmp[0]; | 268 | *outlen = (size_t)tmp[0]; |
268 | memcpy(out, tmp + 4, *outlen); | 269 | memcpy(out, tmp + 4, *outlen); |
269 | rv = 1; | 270 | rv = 1; |
271 | |||
270 | err: | 272 | err: |
271 | OPENSSL_clear_free(tmp, inlen); | 273 | OPENSSL_clear_free(tmp, inlen); |
272 | return rv; | ||
273 | 274 | ||
275 | return rv; | ||
274 | } | 276 | } |
275 | 277 | ||
276 | static int kek_wrap_key(unsigned char *out, size_t *outlen, | 278 | static int |
277 | const unsigned char *in, size_t inlen, | 279 | kek_wrap_key(unsigned char *out, size_t *outlen, const unsigned char *in, |
278 | EVP_CIPHER_CTX *ctx) | 280 | size_t inlen, EVP_CIPHER_CTX *ctx) |
279 | { | 281 | { |
280 | size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); | 282 | size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); |
281 | size_t olen; | 283 | size_t olen; |
282 | int dummy; | 284 | int dummy; |
285 | |||
283 | /* | 286 | /* |
284 | * First decide length of output buffer: need header and round up to | 287 | * First decide length of output buffer: need header and round up to |
285 | * multiple of block length. | 288 | * multiple of block length. |
@@ -302,12 +305,12 @@ static int kek_wrap_key(unsigned char *out, size_t *outlen, | |||
302 | out[3] = in[2] ^ 0xFF; | 305 | out[3] = in[2] ^ 0xFF; |
303 | memcpy(out + 4, in, inlen); | 306 | memcpy(out + 4, in, inlen); |
304 | /* Add random padding to end */ | 307 | /* Add random padding to end */ |
305 | if (olen > inlen + 4 | 308 | if (olen > inlen + 4 && |
306 | && RAND_bytes(out + 4 + inlen, olen - 4 - inlen) <= 0) | 309 | RAND_bytes(out + 4 + inlen, olen - 4 - inlen) <= 0) |
307 | return 0; | 310 | return 0; |
308 | /* Encrypt twice */ | 311 | /* Encrypt twice */ |
309 | if (!EVP_EncryptUpdate(ctx, out, &dummy, out, olen) | 312 | if (!EVP_EncryptUpdate(ctx, out, &dummy, out, olen) || |
310 | || !EVP_EncryptUpdate(ctx, out, &dummy, out, olen)) | 313 | !EVP_EncryptUpdate(ctx, out, &dummy, out, olen)) |
311 | return 0; | 314 | return 0; |
312 | } | 315 | } |
313 | 316 | ||
@@ -318,8 +321,9 @@ static int kek_wrap_key(unsigned char *out, size_t *outlen, | |||
318 | 321 | ||
319 | /* Encrypt/Decrypt content key in PWRI recipient info */ | 322 | /* Encrypt/Decrypt content key in PWRI recipient info */ |
320 | 323 | ||
321 | int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, | 324 | int |
322 | int en_de) | 325 | cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, |
326 | int en_de) | ||
323 | { | 327 | { |
324 | CMS_EncryptedContentInfo *ec; | 328 | CMS_EncryptedContentInfo *ec; |
325 | CMS_PasswordRecipientInfo *pwri; | 329 | CMS_PasswordRecipientInfo *pwri; |
@@ -342,21 +346,20 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, | |||
342 | 346 | ||
343 | if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) { | 347 | if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) { |
344 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, | 348 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, |
345 | CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); | 349 | CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); |
346 | return 0; | 350 | return 0; |
347 | } | 351 | } |
348 | 352 | ||
349 | kekalg = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR), | 353 | kekalg = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR), |
350 | algtmp->parameter); | 354 | algtmp->parameter); |
351 | 355 | ||
352 | if (kekalg == NULL) { | 356 | if (kekalg == NULL) { |
353 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, | 357 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, |
354 | CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER); | 358 | CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER); |
355 | return 0; | 359 | return 0; |
356 | } | 360 | } |
357 | 361 | ||
358 | kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); | 362 | kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); |
359 | |||
360 | if (!kekcipher) { | 363 | if (!kekcipher) { |
361 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNKNOWN_CIPHER); | 364 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNKNOWN_CIPHER); |
362 | return 0; | 365 | return 0; |
@@ -373,7 +376,7 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, | |||
373 | EVP_CIPHER_CTX_set_padding(kekctx, 0); | 376 | EVP_CIPHER_CTX_set_padding(kekctx, 0); |
374 | if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) { | 377 | if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) { |
375 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, | 378 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, |
376 | CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); | 379 | CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); |
377 | goto err; | 380 | goto err; |
378 | } | 381 | } |
379 | 382 | ||
@@ -381,9 +384,8 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, | |||
381 | 384 | ||
382 | /* Finish password based key derivation to setup key in "ctx" */ | 385 | /* Finish password based key derivation to setup key in "ctx" */ |
383 | 386 | ||
384 | if (EVP_PBE_CipherInit(algtmp->algorithm, | 387 | if (EVP_PBE_CipherInit(algtmp->algorithm, (char *)pwri->pass, |
385 | (char *)pwri->pass, pwri->passlen, | 388 | pwri->passlen, algtmp->parameter, kekctx, en_de) < 0) { |
386 | algtmp->parameter, kekctx, en_de) < 0) { | ||
387 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB); | 389 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB); |
388 | goto err; | 390 | goto err; |
389 | } | 391 | } |
@@ -391,12 +393,10 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, | |||
391 | /* Finally wrap/unwrap the key */ | 393 | /* Finally wrap/unwrap the key */ |
392 | 394 | ||
393 | if (en_de) { | 395 | if (en_de) { |
394 | |||
395 | if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx)) | 396 | if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx)) |
396 | goto err; | 397 | goto err; |
397 | 398 | ||
398 | key = OPENSSL_malloc(keylen); | 399 | key = OPENSSL_malloc(keylen); |
399 | |||
400 | if (key == NULL) | 400 | if (key == NULL) |
401 | goto err; | 401 | goto err; |
402 | 402 | ||
@@ -406,14 +406,12 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, | |||
406 | pwri->encryptedKey->length = keylen; | 406 | pwri->encryptedKey->length = keylen; |
407 | } else { | 407 | } else { |
408 | key = OPENSSL_malloc(pwri->encryptedKey->length); | 408 | key = OPENSSL_malloc(pwri->encryptedKey->length); |
409 | |||
410 | if (key == NULL) { | 409 | if (key == NULL) { |
411 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE); | 410 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE); |
412 | goto err; | 411 | goto err; |
413 | } | 412 | } |
414 | if (!kek_unwrap_key(key, &keylen, | 413 | if (!kek_unwrap_key(key, &keylen, pwri->encryptedKey->data, |
415 | pwri->encryptedKey->data, | 414 | pwri->encryptedKey->length, kekctx)) { |
416 | pwri->encryptedKey->length, kekctx)) { | ||
417 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNWRAP_FAILURE); | 415 | CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNWRAP_FAILURE); |
418 | goto err; | 416 | goto err; |
419 | } | 417 | } |
@@ -421,19 +419,15 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, | |||
421 | OPENSSL_clear_free(ec->key, ec->keylen); | 419 | OPENSSL_clear_free(ec->key, ec->keylen); |
422 | ec->key = key; | 420 | ec->key = key; |
423 | ec->keylen = keylen; | 421 | ec->keylen = keylen; |
424 | |||
425 | } | 422 | } |
426 | 423 | ||
427 | r = 1; | 424 | r = 1; |
428 | 425 | ||
429 | err: | 426 | err: |
430 | |||
431 | EVP_CIPHER_CTX_free(kekctx); | 427 | EVP_CIPHER_CTX_free(kekctx); |
432 | |||
433 | if (!r) | 428 | if (!r) |
434 | OPENSSL_free(key); | 429 | OPENSSL_free(key); |
435 | X509_ALGOR_free(kekalg); | 430 | X509_ALGOR_free(kekalg); |
436 | 431 | ||
437 | return r; | 432 | return r; |
438 | |||
439 | } | 433 | } |