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 | } |
