mirror of https://github.com/openssl/openssl.git
				
				
				
			Experimental CMS password based recipient Info support.
This commit is contained in:
		
							parent
							
								
									480af99ef4
								
							
						
					
					
						commit
						d2a53c2238
					
				
							
								
								
									
										4
									
								
								CHANGES
								
								
								
								
							
							
						
						
									
										4
									
								
								CHANGES
								
								
								
								
							|  | @ -4,6 +4,10 @@ | |||
| 
 | ||||
|  Changes between 1.0.0 and 1.1.0  [xx XXX xxxx] | ||||
| 
 | ||||
|   *) Experiemental password based recipient info support for CMS library: | ||||
|      implementing RFC3211. | ||||
|      [Steve Henson] | ||||
| 
 | ||||
|   *) Split password based encryption into PBES2 and PBKDF2 functions. This | ||||
|      neatly separates the code into cipher and PBE sections and is required | ||||
|      for some algorithms that split PBES2 into separate pieces (such as | ||||
|  |  | |||
							
								
								
									
										35
									
								
								apps/cms.c
								
								
								
								
							
							
						
						
									
										35
									
								
								apps/cms.c
								
								
								
								
							|  | @ -136,6 +136,7 @@ int MAIN(int argc, char **argv) | |||
| 	char *engine=NULL; | ||||
| #endif | ||||
| 	unsigned char *secret_key = NULL, *secret_keyid = NULL; | ||||
| 	unsigned char *pwri_pass = NULL, *pwri_tmp = NULL; | ||||
| 	size_t secret_keylen = 0, secret_keyidlen = 0; | ||||
| 
 | ||||
| 	ASN1_OBJECT *econtent_type = NULL; | ||||
|  | @ -326,6 +327,13 @@ int MAIN(int argc, char **argv) | |||
| 				} | ||||
| 			secret_keyidlen = (size_t)ltmp; | ||||
| 			} | ||||
| 		else if (!strcmp(*args,"-pwri_password")) | ||||
| 			{ | ||||
| 			if (!args[1]) | ||||
| 				goto argerr; | ||||
| 			args++; | ||||
| 			pwri_pass = (unsigned char *)*args; | ||||
| 			} | ||||
| 		else if (!strcmp(*args,"-econtent_type")) | ||||
| 			{ | ||||
| 			if (!args[1]) | ||||
|  | @ -559,7 +567,7 @@ int MAIN(int argc, char **argv) | |||
| 
 | ||||
| 	else if (operation == SMIME_DECRYPT) | ||||
| 		{ | ||||
| 		if (!recipfile && !keyfile && !secret_key) | ||||
| 		if (!recipfile && !keyfile && !secret_key && !pwri_pass) | ||||
| 			{ | ||||
| 			BIO_printf(bio_err, "No recipient certificate or key specified\n"); | ||||
| 			badarg = 1; | ||||
|  | @ -567,7 +575,7 @@ int MAIN(int argc, char **argv) | |||
| 		} | ||||
| 	else if (operation == SMIME_ENCRYPT) | ||||
| 		{ | ||||
| 		if (!*args && !secret_key) | ||||
| 		if (!*args && !secret_key && !pwri_pass) | ||||
| 			{ | ||||
| 			BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); | ||||
| 			badarg = 1; | ||||
|  | @ -917,6 +925,17 @@ int MAIN(int argc, char **argv) | |||
| 			secret_key = NULL; | ||||
| 			secret_keyid = NULL; | ||||
| 			} | ||||
| 		if (pwri_pass) | ||||
| 			{ | ||||
| 			pwri_tmp = (unsigned char *)BUF_strdup((char *)pwri_pass); | ||||
| 			if (!pwri_tmp) | ||||
| 				goto end; | ||||
| 			if (!CMS_add0_recipient_password(cms, | ||||
| 						-1, NID_undef, NID_undef, | ||||
| 						 pwri_tmp, -1, NULL)) | ||||
| 				goto end; | ||||
| 			pwri_tmp = NULL; | ||||
| 			} | ||||
| 		if (!(flags & CMS_STREAM)) | ||||
| 			{ | ||||
| 			if (!CMS_final(cms, in, NULL, flags)) | ||||
|  | @ -1043,6 +1062,16 @@ int MAIN(int argc, char **argv) | |||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 		if (pwri_pass) | ||||
| 			{ | ||||
| 			if (!CMS_decrypt_set1_password(cms, pwri_pass, -1)) | ||||
| 				{ | ||||
| 				BIO_puts(bio_err, | ||||
| 					"Error decrypting CMS using password\n"); | ||||
| 				goto end; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 		if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags)) | ||||
| 			{ | ||||
| 			BIO_printf(bio_err, "Error decrypting CMS structure\n"); | ||||
|  | @ -1167,6 +1196,8 @@ end: | |||
| 		OPENSSL_free(secret_key); | ||||
| 	if (secret_keyid) | ||||
| 		OPENSSL_free(secret_keyid); | ||||
| 	if (pwri_tmp) | ||||
| 		OPENSSL_free(pwri_tmp); | ||||
| 	if (econtent_type) | ||||
| 		ASN1_OBJECT_free(econtent_type); | ||||
| 	if (rr) | ||||
|  |  | |||
|  | @ -18,9 +18,11 @@ APPS= | |||
| 
 | ||||
| LIB=$(TOP)/libcrypto.a | ||||
| LIBSRC= cms_lib.c cms_asn1.c cms_att.c cms_io.c cms_smime.c cms_err.c \
 | ||||
| 	cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c cms_ess.c | ||||
| 	cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c cms_ess.c \
 | ||||
| 	cms_pwri.c | ||||
| LIBOBJ= cms_lib.o cms_asn1.o cms_att.o cms_io.o cms_smime.o cms_err.o \
 | ||||
| 	cms_sd.o cms_dd.o cms_cd.o cms_env.o cms_enc.o cms_ess.o | ||||
| 	cms_sd.o cms_dd.o cms_cd.o cms_env.o cms_enc.o cms_ess.o \
 | ||||
| 	cms_pwri.o | ||||
| 
 | ||||
| SRC= $(LIBSRC) | ||||
| 
 | ||||
|  |  | |||
|  | @ -184,6 +184,8 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert); | |||
| int CMS_decrypt_set1_key(CMS_ContentInfo *cms,  | ||||
| 				unsigned char *key, size_t keylen, | ||||
| 				unsigned char *id, size_t idlen); | ||||
| int CMS_decrypt_set1_password(CMS_ContentInfo *cms,  | ||||
| 				unsigned char *pass, ssize_t passlen); | ||||
| 
 | ||||
| STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms); | ||||
| int CMS_RecipientInfo_type(CMS_RecipientInfo *ri); | ||||
|  | @ -219,6 +221,14 @@ int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, | |||
| int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,  | ||||
| 					const unsigned char *id, size_t idlen); | ||||
| 
 | ||||
| int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,  | ||||
| 					unsigned char *pass, ssize_t passlen); | ||||
| 
 | ||||
| CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, | ||||
| 					int iter, int wrap_nid, int pbe_nid, | ||||
| 					unsigned char *pass, ssize_t passlen, | ||||
| 					const EVP_CIPHER *kekciph); | ||||
| 
 | ||||
| int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri); | ||||
| 	 | ||||
| int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, | ||||
|  | @ -330,6 +340,7 @@ void ERR_load_CMS_strings(void); | |||
| #define CMS_F_CHECK_CONTENT				 99 | ||||
| #define CMS_F_CMS_ADD0_CERT				 164 | ||||
| #define CMS_F_CMS_ADD0_RECIPIENT_KEY			 100 | ||||
| #define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD		 165 | ||||
| #define CMS_F_CMS_ADD1_RECEIPTREQUEST			 158 | ||||
| #define CMS_F_CMS_ADD1_RECIPIENT_CERT			 101 | ||||
| #define CMS_F_CMS_ADD1_SIGNER				 102 | ||||
|  | @ -344,6 +355,7 @@ void ERR_load_CMS_strings(void); | |||
| #define CMS_F_CMS_DATAINIT				 111 | ||||
| #define CMS_F_CMS_DECRYPT				 112 | ||||
| #define CMS_F_CMS_DECRYPT_SET1_KEY			 113 | ||||
| #define CMS_F_CMS_DECRYPT_SET1_PASSWORD			 166 | ||||
| #define CMS_F_CMS_DECRYPT_SET1_PKEY			 114 | ||||
| #define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX		 115 | ||||
| #define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO		 116 | ||||
|  | @ -378,7 +390,9 @@ void ERR_load_CMS_strings(void); | |||
| #define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT		 141 | ||||
| #define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS		 142 | ||||
| #define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID	 143 | ||||
| #define CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT		 167 | ||||
| #define CMS_F_CMS_RECIPIENTINFO_SET0_KEY		 144 | ||||
| #define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD		 168 | ||||
| #define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY		 145 | ||||
| #define CMS_F_CMS_SET1_SIGNERIDENTIFIER			 146 | ||||
| #define CMS_F_CMS_SET_DETACHED				 147 | ||||
|  | @ -419,6 +433,7 @@ void ERR_load_CMS_strings(void); | |||
| #define CMS_R_ERROR_SETTING_KEY				 115 | ||||
| #define CMS_R_ERROR_SETTING_RECIPIENTINFO		 116 | ||||
| #define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH		 117 | ||||
| #define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER		 176 | ||||
| #define CMS_R_INVALID_KEY_LENGTH			 118 | ||||
| #define CMS_R_MD_BIO_INIT_ERROR				 119 | ||||
| #define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH	 120 | ||||
|  | @ -431,6 +446,7 @@ void ERR_load_CMS_strings(void); | |||
| #define CMS_R_NOT_ENCRYPTED_DATA			 122 | ||||
| #define CMS_R_NOT_KEK					 123 | ||||
| #define CMS_R_NOT_KEY_TRANSPORT				 124 | ||||
| #define CMS_R_NOT_PWRI					 177 | ||||
| #define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE		 125 | ||||
| #define CMS_R_NO_CIPHER					 126 | ||||
| #define CMS_R_NO_CONTENT				 127 | ||||
|  | @ -443,6 +459,7 @@ void ERR_load_CMS_strings(void); | |||
| #define CMS_R_NO_MATCHING_RECIPIENT			 132 | ||||
| #define CMS_R_NO_MATCHING_SIGNATURE			 166 | ||||
| #define CMS_R_NO_MSGSIGDIGEST				 167 | ||||
| #define CMS_R_NO_PASSWORD				 178 | ||||
| #define CMS_R_NO_PRIVATE_KEY				 133 | ||||
| #define CMS_R_NO_PUBLIC_KEY				 134 | ||||
| #define CMS_R_NO_RECEIPT_REQUEST			 168 | ||||
|  | @ -466,10 +483,12 @@ void ERR_load_CMS_strings(void); | |||
| #define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 151 | ||||
| #define CMS_R_UNSUPPORTED_CONTENT_TYPE			 152 | ||||
| #define CMS_R_UNSUPPORTED_KEK_ALGORITHM			 153 | ||||
| #define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM	 179 | ||||
| #define CMS_R_UNSUPPORTED_RECIPIENT_TYPE		 154 | ||||
| #define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE		 155 | ||||
| #define CMS_R_UNSUPPORTED_TYPE				 156 | ||||
| #define CMS_R_UNWRAP_ERROR				 157 | ||||
| #define CMS_R_UNWRAP_FAILURE				 180 | ||||
| #define CMS_R_VERIFICATION_FAILURE			 158 | ||||
| #define CMS_R_WRAP_ERROR				 159 | ||||
| 
 | ||||
|  |  | |||
|  | @ -237,6 +237,15 @@ static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, | |||
| 				OPENSSL_free(kekri->key); | ||||
| 				} | ||||
| 			} | ||||
| 		else if (ri->type == CMS_RECIPINFO_PASS) | ||||
| 			{ | ||||
| 			CMS_PasswordRecipientInfo *pwri = ri->d.pwri; | ||||
| 			if (pwri->pass) | ||||
| 				{ | ||||
| 				OPENSSL_cleanse(pwri->pass, pwri->passlen); | ||||
| 				OPENSSL_free(pwri->pass); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	return 1; | ||||
| 	} | ||||
|  |  | |||
|  | @ -65,14 +65,13 @@ | |||
| /* CMS EnvelopedData Utilities */ | ||||
| 
 | ||||
| DECLARE_ASN1_ITEM(CMS_EnvelopedData) | ||||
| DECLARE_ASN1_ITEM(CMS_RecipientInfo) | ||||
| DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo) | ||||
| DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo) | ||||
| DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute) | ||||
| 
 | ||||
| DECLARE_STACK_OF(CMS_RecipientInfo) | ||||
| 
 | ||||
| static CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms) | ||||
| CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms) | ||||
| 	{ | ||||
| 	if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) | ||||
| 		{ | ||||
|  | @ -786,6 +785,9 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) | |||
| 		case CMS_RECIPINFO_KEK: | ||||
| 		return cms_RecipientInfo_kekri_decrypt(cms, ri); | ||||
| 
 | ||||
| 		case CMS_RECIPINFO_PASS: | ||||
| 		return cms_RecipientInfo_pwri_crypt(cms, ri, 0); | ||||
| 
 | ||||
| 		default: | ||||
| 		CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, | ||||
| 			CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE); | ||||
|  | @ -829,6 +831,10 @@ BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) | |||
| 			r = cms_RecipientInfo_kekri_encrypt(cms, ri); | ||||
| 			break; | ||||
| 
 | ||||
| 			case CMS_RECIPINFO_PASS: | ||||
| 			r = cms_RecipientInfo_pwri_crypt(cms, ri, 1); | ||||
| 			break; | ||||
| 
 | ||||
| 			default: | ||||
| 			CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, | ||||
| 				CMS_R_UNSUPPORTED_RECIPIENT_TYPE); | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| /* crypto/cms/cms_err.c */ | ||||
| /* ====================================================================
 | ||||
|  * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved. | ||||
|  * Copyright (c) 1999-2009 The OpenSSL Project.  All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  | @ -73,6 +73,7 @@ static ERR_STRING_DATA CMS_str_functs[]= | |||
| {ERR_FUNC(CMS_F_CHECK_CONTENT),	"CHECK_CONTENT"}, | ||||
| {ERR_FUNC(CMS_F_CMS_ADD0_CERT),	"CMS_add0_cert"}, | ||||
| {ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_KEY),	"CMS_add0_recipient_key"}, | ||||
| {ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD),	"CMS_add0_recipient_password"}, | ||||
| {ERR_FUNC(CMS_F_CMS_ADD1_RECEIPTREQUEST),	"CMS_add1_ReceiptRequest"}, | ||||
| {ERR_FUNC(CMS_F_CMS_ADD1_RECIPIENT_CERT),	"CMS_add1_recipient_cert"}, | ||||
| {ERR_FUNC(CMS_F_CMS_ADD1_SIGNER),	"CMS_add1_signer"}, | ||||
|  | @ -87,6 +88,7 @@ static ERR_STRING_DATA CMS_str_functs[]= | |||
| {ERR_FUNC(CMS_F_CMS_DATAINIT),	"CMS_dataInit"}, | ||||
| {ERR_FUNC(CMS_F_CMS_DECRYPT),	"CMS_decrypt"}, | ||||
| {ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_KEY),	"CMS_decrypt_set1_key"}, | ||||
| {ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_PASSWORD),	"CMS_decrypt_set1_password"}, | ||||
| {ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_PKEY),	"CMS_decrypt_set1_pkey"}, | ||||
| {ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX),	"cms_DigestAlgorithm_find_ctx"}, | ||||
| {ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO),	"cms_DigestAlgorithm_init_bio"}, | ||||
|  | @ -105,7 +107,7 @@ static ERR_STRING_DATA CMS_str_functs[]= | |||
| {ERR_FUNC(CMS_F_CMS_GET0_CERTIFICATE_CHOICES),	"CMS_GET0_CERTIFICATE_CHOICES"}, | ||||
| {ERR_FUNC(CMS_F_CMS_GET0_CONTENT),	"CMS_get0_content"}, | ||||
| {ERR_FUNC(CMS_F_CMS_GET0_ECONTENT_TYPE),	"CMS_GET0_ECONTENT_TYPE"}, | ||||
| {ERR_FUNC(CMS_F_CMS_GET0_ENVELOPED),	"CMS_GET0_ENVELOPED"}, | ||||
| {ERR_FUNC(CMS_F_CMS_GET0_ENVELOPED),	"cms_get0_enveloped"}, | ||||
| {ERR_FUNC(CMS_F_CMS_GET0_REVOCATION_CHOICES),	"CMS_GET0_REVOCATION_CHOICES"}, | ||||
| {ERR_FUNC(CMS_F_CMS_GET0_SIGNED),	"CMS_GET0_SIGNED"}, | ||||
| {ERR_FUNC(CMS_F_CMS_MSGSIGDIGEST_ADD1),	"cms_msgSigDigest_add1"}, | ||||
|  | @ -121,7 +123,9 @@ static ERR_STRING_DATA CMS_str_functs[]= | |||
| {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT),	"CMS_RECIPIENTINFO_KTRI_ENCRYPT"}, | ||||
| {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS),	"CMS_RecipientInfo_ktri_get0_algs"}, | ||||
| {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID),	"CMS_RecipientInfo_ktri_get0_signer_id"}, | ||||
| {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT),	"cms_RecipientInfo_pwri_crypt"}, | ||||
| {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_KEY),	"CMS_RecipientInfo_set0_key"}, | ||||
| {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD),	"CMS_RecipientInfo_set0_password"}, | ||||
| {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY),	"CMS_RecipientInfo_set0_pkey"}, | ||||
| {ERR_FUNC(CMS_F_CMS_SET1_SIGNERIDENTIFIER),	"cms_set1_SignerIdentifier"}, | ||||
| {ERR_FUNC(CMS_F_CMS_SET_DETACHED),	"CMS_set_detached"}, | ||||
|  | @ -165,6 +169,7 @@ static ERR_STRING_DATA CMS_str_reasons[]= | |||
| {ERR_REASON(CMS_R_ERROR_SETTING_KEY)     ,"error setting key"}, | ||||
| {ERR_REASON(CMS_R_ERROR_SETTING_RECIPIENTINFO),"error setting recipientinfo"}, | ||||
| {ERR_REASON(CMS_R_INVALID_ENCRYPTED_KEY_LENGTH),"invalid encrypted key length"}, | ||||
| {ERR_REASON(CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER),"invalid key encryption parameter"}, | ||||
| {ERR_REASON(CMS_R_INVALID_KEY_LENGTH)    ,"invalid key length"}, | ||||
| {ERR_REASON(CMS_R_MD_BIO_INIT_ERROR)     ,"md bio init error"}, | ||||
| {ERR_REASON(CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),"messagedigest attribute wrong length"}, | ||||
|  | @ -177,6 +182,7 @@ static ERR_STRING_DATA CMS_str_reasons[]= | |||
| {ERR_REASON(CMS_R_NOT_ENCRYPTED_DATA)    ,"not encrypted data"}, | ||||
| {ERR_REASON(CMS_R_NOT_KEK)               ,"not kek"}, | ||||
| {ERR_REASON(CMS_R_NOT_KEY_TRANSPORT)     ,"not key transport"}, | ||||
| {ERR_REASON(CMS_R_NOT_PWRI)              ,"not pwri"}, | ||||
| {ERR_REASON(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE),"not supported for this key type"}, | ||||
| {ERR_REASON(CMS_R_NO_CIPHER)             ,"no cipher"}, | ||||
| {ERR_REASON(CMS_R_NO_CONTENT)            ,"no content"}, | ||||
|  | @ -189,6 +195,7 @@ static ERR_STRING_DATA CMS_str_reasons[]= | |||
| {ERR_REASON(CMS_R_NO_MATCHING_RECIPIENT) ,"no matching recipient"}, | ||||
| {ERR_REASON(CMS_R_NO_MATCHING_SIGNATURE) ,"no matching signature"}, | ||||
| {ERR_REASON(CMS_R_NO_MSGSIGDIGEST)       ,"no msgsigdigest"}, | ||||
| {ERR_REASON(CMS_R_NO_PASSWORD)           ,"no password"}, | ||||
| {ERR_REASON(CMS_R_NO_PRIVATE_KEY)        ,"no private key"}, | ||||
| {ERR_REASON(CMS_R_NO_PUBLIC_KEY)         ,"no public key"}, | ||||
| {ERR_REASON(CMS_R_NO_RECEIPT_REQUEST)    ,"no receipt request"}, | ||||
|  | @ -212,10 +219,12 @@ static ERR_STRING_DATA CMS_str_reasons[]= | |||
| {ERR_REASON(CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"}, | ||||
| {ERR_REASON(CMS_R_UNSUPPORTED_CONTENT_TYPE),"unsupported content type"}, | ||||
| {ERR_REASON(CMS_R_UNSUPPORTED_KEK_ALGORITHM),"unsupported kek algorithm"}, | ||||
| {ERR_REASON(CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM),"unsupported key encryption algorithm"}, | ||||
| {ERR_REASON(CMS_R_UNSUPPORTED_RECIPIENT_TYPE),"unsupported recipient type"}, | ||||
| {ERR_REASON(CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE),"unsupported recpientinfo type"}, | ||||
| {ERR_REASON(CMS_R_UNSUPPORTED_TYPE)      ,"unsupported type"}, | ||||
| {ERR_REASON(CMS_R_UNWRAP_ERROR)          ,"unwrap error"}, | ||||
| {ERR_REASON(CMS_R_UNWRAP_FAILURE)        ,"unwrap failure"}, | ||||
| {ERR_REASON(CMS_R_VERIFICATION_FAILURE)  ,"verification failure"}, | ||||
| {ERR_REASON(CMS_R_WRAP_ERROR)            ,"wrap error"}, | ||||
| {0,NULL} | ||||
|  |  | |||
|  | @ -273,6 +273,9 @@ struct CMS_PasswordRecipientInfo_st | |||
|  	X509_ALGOR *keyDerivationAlgorithm; | ||||
|  	X509_ALGOR *keyEncryptionAlgorithm; | ||||
|  	ASN1_OCTET_STRING *encryptedKey; | ||||
| 	/* Extra info: password to use */ | ||||
| 	unsigned char *pass; | ||||
| 	size_t passlen; | ||||
| 	}; | ||||
| 
 | ||||
| struct CMS_OtherRecipientInfo_st | ||||
|  | @ -411,6 +414,8 @@ DECLARE_ASN1_ITEM(CMS_SignerInfo) | |||
| DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber) | ||||
| DECLARE_ASN1_ITEM(CMS_Attributes_Sign) | ||||
| DECLARE_ASN1_ITEM(CMS_Attributes_Verify) | ||||
| DECLARE_ASN1_ITEM(CMS_RecipientInfo) | ||||
| DECLARE_ASN1_ITEM(CMS_PasswordRecipientInfo) | ||||
| DECLARE_ASN1_ALLOC_FUNCTIONS(CMS_IssuerAndSerialNumber) | ||||
| 
 | ||||
| #define CMS_SIGNERINFO_ISSUER_SERIAL	0 | ||||
|  | @ -454,6 +459,11 @@ int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src); | |||
| ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si); | ||||
| 
 | ||||
| BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms); | ||||
| CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms); | ||||
| 
 | ||||
| /* PWRI routines */ | ||||
| int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, | ||||
| 							int en_de); | ||||
| 	 | ||||
| #ifdef  __cplusplus | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,453 @@ | |||
| /* crypto/cms/cms_pwri.c */ | ||||
| /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
 | ||||
|  * project. | ||||
|  */ | ||||
| /* ====================================================================
 | ||||
|  * Copyright (c) 2009 The OpenSSL Project.  All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer.  | ||||
|  * | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer in | ||||
|  *    the documentation and/or other materials provided with the | ||||
|  *    distribution. | ||||
|  * | ||||
|  * 3. All advertising materials mentioning features or use of this | ||||
|  *    software must display the following acknowledgment: | ||||
|  *    "This product includes software developed by the OpenSSL Project | ||||
|  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 | ||||
|  * | ||||
|  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | ||||
|  *    endorse or promote products derived from this software without | ||||
|  *    prior written permission. For written permission, please contact | ||||
|  *    licensing@OpenSSL.org. | ||||
|  * | ||||
|  * 5. Products derived from this software may not be called "OpenSSL" | ||||
|  *    nor may "OpenSSL" appear in their names without prior written | ||||
|  *    permission of the OpenSSL Project. | ||||
|  * | ||||
|  * 6. Redistributions of any form whatsoever must retain the following | ||||
|  *    acknowledgment: | ||||
|  *    "This product includes software developed by the OpenSSL Project | ||||
|  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | ||||
|  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||||
|  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR | ||||
|  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||||
|  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||
|  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||||
|  * OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  * ==================================================================== | ||||
|  */ | ||||
| 
 | ||||
| #include "cryptlib.h" | ||||
| #include <openssl/asn1t.h> | ||||
| #include <openssl/pem.h> | ||||
| #include <openssl/x509v3.h> | ||||
| #include <openssl/err.h> | ||||
| #include <openssl/cms.h> | ||||
| #include <openssl/rand.h> | ||||
| #include <openssl/aes.h> | ||||
| #include "cms_lcl.h" | ||||
| #include "asn1_locl.h" | ||||
| 
 | ||||
| int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,  | ||||
| 				unsigned char *pass, ssize_t passlen) | ||||
| 	{ | ||||
| 	CMS_PasswordRecipientInfo *pwri; | ||||
| 	if (ri->type != CMS_RECIPINFO_PASS) | ||||
| 		{ | ||||
| 		CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI); | ||||
| 		return 0; | ||||
| 		} | ||||
| 
 | ||||
| 	pwri = ri->d.pwri; | ||||
| 	pwri->pass = pass; | ||||
| 	if (pass && passlen < 0) | ||||
| 		passlen = strlen((char *)pass); | ||||
| 	pwri->passlen = passlen; | ||||
| 	return 1; | ||||
| 	} | ||||
| 
 | ||||
| CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, | ||||
| 					int iter, int wrap_nid, int pbe_nid, | ||||
| 					unsigned char *pass, ssize_t passlen, | ||||
| 					const EVP_CIPHER *kekciph) | ||||
| 	{ | ||||
| 	CMS_RecipientInfo *ri = NULL; | ||||
| 	CMS_EnvelopedData *env; | ||||
| 	CMS_PasswordRecipientInfo *pwri; | ||||
| 	EVP_CIPHER_CTX ctx; | ||||
| 	X509_ALGOR *encalg = NULL; | ||||
| 	unsigned char iv[EVP_MAX_IV_LENGTH]; | ||||
| 	int ivlen; | ||||
| 	env = cms_get0_enveloped(cms); | ||||
| 	if (!env) | ||||
| 		goto err; | ||||
| 
 | ||||
| 	if (wrap_nid <= 0) | ||||
| 		wrap_nid = NID_id_alg_PWRI_KEK; | ||||
| 
 | ||||
| 	if (pbe_nid <= 0) | ||||
| 		pbe_nid = NID_id_pbkdf2; | ||||
| 
 | ||||
| 	/* Get from enveloped data */ | ||||
| 	if (kekciph == NULL) | ||||
| 		kekciph = env->encryptedContentInfo->cipher; | ||||
| 
 | ||||
| 	if (kekciph == NULL) | ||||
| 		{ | ||||
| 		CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER); | ||||
| 		return NULL; | ||||
| 		} | ||||
| 	if (wrap_nid != NID_id_alg_PWRI_KEK) | ||||
| 		{ | ||||
| 		CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, | ||||
| 				CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); | ||||
| 		return NULL; | ||||
| 		} | ||||
| 
 | ||||
| 	/* Setup algorithm identifier for cipher */ | ||||
| 	encalg = X509_ALGOR_new(); | ||||
| 	EVP_CIPHER_CTX_init(&ctx); | ||||
| 
 | ||||
| 	if (EVP_EncryptInit_ex(&ctx, kekciph, NULL, NULL, NULL) <= 0) | ||||
| 		{ | ||||
| 		CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB); | ||||
| 		goto err; | ||||
| 		} | ||||
| 
 | ||||
| 	ivlen = EVP_CIPHER_CTX_iv_length(&ctx); | ||||
| 
 | ||||
| 	if (ivlen > 0) | ||||
| 		{ | ||||
| 		if (RAND_pseudo_bytes(iv, ivlen) <= 0) | ||||
| 			goto err; | ||||
| 		if (EVP_EncryptInit_ex(&ctx, NULL, NULL, NULL, iv) <= 0) | ||||
| 			{ | ||||
| 			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, | ||||
| 							ERR_R_EVP_LIB); | ||||
| 			goto err; | ||||
| 			} | ||||
| 		encalg->parameter = ASN1_TYPE_new(); | ||||
| 		if (!encalg->parameter) | ||||
| 			{ | ||||
| 			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, | ||||
| 							ERR_R_MALLOC_FAILURE); | ||||
| 			goto err; | ||||
| 			} | ||||
| 		if (EVP_CIPHER_param_to_asn1(&ctx, encalg->parameter) <= 0) | ||||
| 			{ | ||||
| 			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, | ||||
| 				CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); | ||||
| 			goto err; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| 	encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(&ctx)); | ||||
| 
 | ||||
| 	EVP_CIPHER_CTX_cleanup(&ctx); | ||||
| 
 | ||||
| 	/* Initialize recipient info */ | ||||
| 	ri = M_ASN1_new_of(CMS_RecipientInfo); | ||||
| 	if (!ri) | ||||
| 		goto merr; | ||||
| 
 | ||||
| 	ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo); | ||||
| 	if (!ri->d.pwri) | ||||
| 		goto merr; | ||||
| 	ri->type = CMS_RECIPINFO_PASS; | ||||
| 
 | ||||
| 	pwri = ri->d.pwri; | ||||
| 	/* Since this is overwritten, free up empty structure already there */ | ||||
| 	X509_ALGOR_free(pwri->keyEncryptionAlgorithm); | ||||
| 	pwri->keyEncryptionAlgorithm = X509_ALGOR_new(); | ||||
| 	if (!pwri->keyEncryptionAlgorithm) | ||||
| 		goto merr; | ||||
| 	pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid); | ||||
| 	pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new(); | ||||
| 	if (!pwri->keyEncryptionAlgorithm->parameter) | ||||
| 		goto merr; | ||||
| 
 | ||||
|         if(!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR), | ||||
| 	    &pwri->keyEncryptionAlgorithm->parameter->value.sequence)) | ||||
| 		goto merr; | ||||
|         pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE; | ||||
| 
 | ||||
| 	X509_ALGOR_free(encalg); | ||||
| 	encalg = NULL; | ||||
| 
 | ||||
| 	/* Setup PBE algorithm */ | ||||
| 
 | ||||
| 	pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1); | ||||
| 
 | ||||
| 	if (!pwri->keyDerivationAlgorithm) | ||||
| 		goto err; | ||||
| 
 | ||||
| 	CMS_RecipientInfo_set0_password(ri, pass, passlen); | ||||
| 	pwri->version = 0; | ||||
| 
 | ||||
| 	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) | ||||
| 		goto merr; | ||||
| 
 | ||||
| 	return ri; | ||||
| 
 | ||||
| 	merr: | ||||
| 	CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE); | ||||
| 	err: | ||||
| 	EVP_CIPHER_CTX_cleanup(&ctx); | ||||
| 	if (ri) | ||||
| 		M_ASN1_free_of(ri, CMS_RecipientInfo); | ||||
| 	if (encalg) | ||||
| 		X509_ALGOR_free(encalg); | ||||
| 	return NULL; | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| /* This is an implementation of the key wrapping mechanism in RFC3211,
 | ||||
|  * at some point this should go into EVP. | ||||
|  */ | ||||
| 
 | ||||
| static int kek_unwrap_key(unsigned char *out, size_t *outlen, | ||||
| 		const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx) | ||||
| 	{ | ||||
| 	size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); | ||||
| 	unsigned char *tmp; | ||||
| 	int outl, rv = 0; | ||||
| 	if (inlen < 2 * blocklen) | ||||
| 		{ | ||||
| 		/* too small */ | ||||
| 		return 0; | ||||
| 		} | ||||
| 	if (inlen % blocklen) | ||||
| 		{ | ||||
| 		/* Invalid size */ | ||||
| 		return 0; | ||||
| 		} | ||||
| 	tmp = OPENSSL_malloc(inlen); | ||||
| 	/* setup IV by decrypting last two blocks */ | ||||
| 	EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl, | ||||
| 				in  + inlen - 2 * blocklen, blocklen * 2); | ||||
| 	/* Do a decrypt of last decrypted block to set IV to correct value
 | ||||
| 	 * output it to start of buffer so we don't corrupt decrypted block | ||||
| 	 * this works because buffer is at least two block lengths long. | ||||
| 	 */ | ||||
| 	EVP_DecryptUpdate(ctx, tmp, &outl, | ||||
| 				tmp  + inlen - blocklen, blocklen); | ||||
| 	/* Can now decrypt first n - 1 blocks */ | ||||
| 	EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen); | ||||
| 
 | ||||
| 	/* Reset IV to original value */ | ||||
| 	EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL); | ||||
| 	/* Decrypt again */ | ||||
| 	EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen); | ||||
| 	/* Check check bytes */ | ||||
| 	if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff) | ||||
| 		{ | ||||
| 		/* Check byte failure */ | ||||
| 		goto err; | ||||
| 		} | ||||
| 	if (inlen < (size_t)(tmp[0] - 4 )) | ||||
| 		{ | ||||
| 		/* Invalid length value */ | ||||
| 		goto err; | ||||
| 		} | ||||
| 	*outlen = (size_t)tmp[0]; | ||||
| 	memcpy(out, tmp + 4, *outlen); | ||||
| 	rv = 1; | ||||
| 	err: | ||||
| 	OPENSSL_cleanse(tmp, inlen); | ||||
| 	OPENSSL_free(tmp); | ||||
| 	return rv; | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| static int kek_wrap_key(unsigned char *out, size_t *outlen, | ||||
| 		const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx) | ||||
| 	{ | ||||
| 	size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); | ||||
| 	size_t olen; | ||||
| 	int dummy; | ||||
| 	/* First decide length of output buffer: need header and round up to
 | ||||
| 	 * multiple of block length. | ||||
| 	 */ | ||||
| 	olen = (inlen + 4 + blocklen - 1)/blocklen; | ||||
| 	olen *= blocklen; | ||||
| 	if (olen < 2 * blocklen) | ||||
| 		{ | ||||
| 		/* Key too small */ | ||||
| 		return 0; | ||||
| 		} | ||||
| 	if (inlen > 0xFF) | ||||
| 		{ | ||||
| 		/* Key too large */ | ||||
| 		return 0; | ||||
| 		} | ||||
| 	if (out) | ||||
| 		{ | ||||
| 		/* Set header */ | ||||
| 		out[0] = (unsigned char)inlen; | ||||
| 		out[1] = in[0] ^ 0xFF; | ||||
| 		out[2] = in[1] ^ 0xFF; | ||||
| 		out[3] = in[2] ^ 0xFF; | ||||
| 		memcpy(out + 4, in, inlen); | ||||
| 		/* Add random padding to end */ | ||||
| 		if (olen > inlen + 4) | ||||
| 			RAND_pseudo_bytes(out + 4 + inlen, olen - 4 - inlen); | ||||
| 		/* Encrypt twice */ | ||||
| 		EVP_EncryptUpdate(ctx, out, &dummy, out, olen); | ||||
| 		EVP_EncryptUpdate(ctx, out, &dummy, out, olen); | ||||
| 		} | ||||
| 
 | ||||
| 	*outlen = olen; | ||||
| 
 | ||||
| 	return 1; | ||||
| 	} | ||||
| 
 | ||||
| /* Encrypt/Decrypt content key in PWRI recipient info */ | ||||
| 
 | ||||
| int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, | ||||
| 							int en_de) | ||||
| 	{ | ||||
| 	CMS_EncryptedContentInfo *ec; | ||||
| 	CMS_PasswordRecipientInfo *pwri; | ||||
| 	const unsigned char *p = NULL; | ||||
| 	int plen; | ||||
| 	int r = 0; | ||||
| 	X509_ALGOR *algtmp, *kekalg = NULL; | ||||
| 	EVP_CIPHER_CTX kekctx; | ||||
| 	const EVP_CIPHER *kekcipher; | ||||
| 	unsigned char *key = NULL; | ||||
| 	size_t keylen; | ||||
| 
 | ||||
| 	ec = cms->d.envelopedData->encryptedContentInfo; | ||||
| 
 | ||||
| 	pwri = ri->d.pwri; | ||||
| 	EVP_CIPHER_CTX_init(&kekctx); | ||||
| 
 | ||||
| 	if (!pwri->pass) | ||||
| 		{ | ||||
| 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD); | ||||
| 		return 0; | ||||
| 		} | ||||
| 	algtmp = pwri->keyEncryptionAlgorithm; | ||||
| 
 | ||||
| 	if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) | ||||
| 		{ | ||||
| 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, | ||||
| 				CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); | ||||
| 		return 0; | ||||
| 		} | ||||
| 
 | ||||
| 	if (algtmp->parameter->type == V_ASN1_SEQUENCE) | ||||
| 		{ | ||||
| 		p = algtmp->parameter->value.sequence->data; | ||||
| 		plen = algtmp->parameter->value.sequence->length; | ||||
| 		kekalg = d2i_X509_ALGOR(NULL, &p, plen); | ||||
| 		} | ||||
| 	if (kekalg == NULL) | ||||
| 		{ | ||||
| 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, | ||||
| 				CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER); | ||||
| 		return 0; | ||||
| 		} | ||||
| 
 | ||||
| 	kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); | ||||
| 		 | ||||
| 	if(!kekcipher) | ||||
| 		{ | ||||
| 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, | ||||
| 				CMS_R_UNKNOWN_CIPHER); | ||||
| 		goto err; | ||||
| 		} | ||||
| 
 | ||||
| 	/* Fixup cipher based on AlgorithmIdentifier to set IV etc */ | ||||
| 	if (!EVP_CipherInit_ex(&kekctx, kekcipher, NULL, NULL, NULL, en_de)) | ||||
| 		goto err; | ||||
| 	EVP_CIPHER_CTX_set_padding(&kekctx, 0); | ||||
| 	if(EVP_CIPHER_asn1_to_param(&kekctx, kekalg->parameter) < 0) | ||||
| 		{ | ||||
| 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, | ||||
| 				CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); | ||||
| 		goto err; | ||||
| 		} | ||||
| 
 | ||||
| 	algtmp = pwri->keyDerivationAlgorithm; | ||||
| 
 | ||||
| 	/* Finish password based key derivation to setup key in "ctx" */ | ||||
| 
 | ||||
| 	if (EVP_PBE_CipherInit(algtmp->algorithm, | ||||
| 				(char *)pwri->pass, pwri->passlen, | ||||
| 				algtmp->parameter, &kekctx, en_de) < 0) | ||||
| 		{ | ||||
| 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB); | ||||
| 		goto err; | ||||
| 		} | ||||
| 
 | ||||
| 	/* Finally wrap/unwrap the key */ | ||||
| 
 | ||||
| 	if (en_de) | ||||
| 		{ | ||||
| 
 | ||||
| 		if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, &kekctx)) | ||||
| 			goto err; | ||||
| 
 | ||||
| 		key = OPENSSL_malloc(keylen); | ||||
| 
 | ||||
| 		if (!key) | ||||
| 			goto err; | ||||
| 
 | ||||
| 		if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, &kekctx)) | ||||
| 			goto err; | ||||
| 		pwri->encryptedKey->data = key; | ||||
| 		pwri->encryptedKey->length = keylen; | ||||
| 		} | ||||
| 	else | ||||
| 		{ | ||||
| 		key = OPENSSL_malloc(pwri->encryptedKey->length); | ||||
| 
 | ||||
| 		if (!key) | ||||
| 			{ | ||||
| 			CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, | ||||
| 							ERR_R_MALLOC_FAILURE); | ||||
| 			goto err; | ||||
| 			} | ||||
| 		if (!kek_unwrap_key(key, &keylen, | ||||
| 					pwri->encryptedKey->data, | ||||
| 					pwri->encryptedKey->length, &kekctx)) | ||||
| 			{ | ||||
| 			CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, | ||||
| 							CMS_R_UNWRAP_FAILURE); | ||||
| 			goto err; | ||||
| 			} | ||||
| 
 | ||||
| 		ec->key = key; | ||||
| 		ec->keylen = keylen; | ||||
| 
 | ||||
| 		} | ||||
| 
 | ||||
| 	r = 1; | ||||
| 
 | ||||
| 	err: | ||||
| 
 | ||||
| 	EVP_CIPHER_CTX_cleanup(&kekctx); | ||||
| 
 | ||||
| 	if (!r && key) | ||||
| 		OPENSSL_free(key); | ||||
| 	X509_ALGOR_free(kekalg); | ||||
| 
 | ||||
| 	return r; | ||||
| 
 | ||||
| 	} | ||||
|  | @ -681,6 +681,30 @@ int CMS_decrypt_set1_key(CMS_ContentInfo *cms, | |||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| int CMS_decrypt_set1_password(CMS_ContentInfo *cms,  | ||||
| 				unsigned char *pass, ssize_t passlen) | ||||
| 	{ | ||||
| 	STACK_OF(CMS_RecipientInfo) *ris; | ||||
| 	CMS_RecipientInfo *ri; | ||||
| 	int i, r; | ||||
| 	ris = CMS_get0_RecipientInfos(cms); | ||||
| 	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) | ||||
| 		{ | ||||
| 		ri = sk_CMS_RecipientInfo_value(ris, i); | ||||
| 		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS) | ||||
| 				continue; | ||||
| 		CMS_RecipientInfo_set0_password(ri, pass, passlen); | ||||
| 		r = CMS_RecipientInfo_decrypt(cms, ri); | ||||
| 		CMS_RecipientInfo_set0_password(ri, NULL, 0); | ||||
| 		if (r > 0) | ||||
| 			return 1; | ||||
| 		} | ||||
| 
 | ||||
| 	CMSerr(CMS_F_CMS_DECRYPT_SET1_PASSWORD, CMS_R_NO_MATCHING_RECIPIENT); | ||||
| 	return 0; | ||||
| 
 | ||||
| 	} | ||||
| 	 | ||||
| int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, | ||||
| 				BIO *dcont, BIO *out, | ||||
| 				unsigned int flags) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue