| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  | /* p12_mutl.c */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project | 
					
						
							|  |  |  |  * 1999. | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | /* ====================================================================
 | 
					
						
							|  |  |  |  * Copyright (c) 1999 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 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  *    notice, this list of conditions and the following disclaimer. | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  * ==================================================================== | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This product includes cryptographic software written by Eric Young | 
					
						
							|  |  |  |  * (eay@cryptsoft.com).  This product includes software written by Tim | 
					
						
							|  |  |  |  * Hudson (tjh@cryptsoft.com). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2015-05-14 22:56:48 +08:00
										 |  |  | # include "internal/cryptlib.h"
 | 
					
						
							| 
									
										
										
										
											2015-05-27 23:12:13 +08:00
										 |  |  | #include <openssl/crypto.h>
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # include <openssl/hmac.h>
 | 
					
						
							|  |  |  | # include <openssl/rand.h>
 | 
					
						
							|  |  |  | # include <openssl/pkcs12.h>
 | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-02 18:27:31 +08:00
										 |  |  | # define TK26_MAC_KEY_LEN 32
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int pkcs12_gen_gost_mac_key(const char *pass, int passlen, | 
					
						
							|  |  |  |                                    const unsigned char *salt, int saltlen, | 
					
						
							|  |  |  |                                    int iter, int keylen, unsigned char *key, | 
					
						
							|  |  |  |                                    const EVP_MD *digest) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned char out[96]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (keylen != TK26_MAC_KEY_LEN) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, | 
					
						
							|  |  |  |                            digest, sizeof(out), out)) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     memcpy(key, out + sizeof(out) - TK26_MAC_KEY_LEN, TK26_MAC_KEY_LEN); | 
					
						
							|  |  |  |     OPENSSL_cleanse(out, sizeof(out)); | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  | /* Generate a MAC */ | 
					
						
							| 
									
										
										
										
											2005-05-11 11:45:39 +08:00
										 |  |  | int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                    unsigned char *mac, unsigned int *maclen) | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     const EVP_MD *md_type; | 
					
						
							|  |  |  |     HMAC_CTX hmac; | 
					
						
							|  |  |  |     unsigned char key[EVP_MAX_MD_SIZE], *salt; | 
					
						
							|  |  |  |     int saltlen, iter; | 
					
						
							| 
									
										
										
										
											2015-09-02 18:27:31 +08:00
										 |  |  |     int md_size = 0; | 
					
						
							|  |  |  |     int md_type_nid; | 
					
						
							| 
									
										
										
										
											2001-07-31 07:57:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (!PKCS7_type_is_data(p12->authsafes)) { | 
					
						
							|  |  |  |         PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_CONTENT_TYPE_NOT_DATA); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-06-30 19:34:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     salt = p12->mac->salt->data; | 
					
						
							|  |  |  |     saltlen = p12->mac->salt->length; | 
					
						
							|  |  |  |     if (!p12->mac->iter) | 
					
						
							|  |  |  |         iter = 1; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         iter = ASN1_INTEGER_get(p12->mac->iter); | 
					
						
							| 
									
										
										
										
											2015-05-07 01:43:59 +08:00
										 |  |  |     if ((md_type = EVP_get_digestbyobj(p12->mac->dinfo->algor->algorithm)) | 
					
						
							|  |  |  |             == NULL) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     md_size = EVP_MD_size(md_type); | 
					
						
							| 
									
										
										
										
											2015-09-02 18:27:31 +08:00
										 |  |  |     md_type_nid = EVP_MD_type(md_type); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (md_size < 0) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2015-09-02 18:27:31 +08:00
										 |  |  |     if ((md_type_nid == NID_id_GostR3411_94 | 
					
						
							|  |  |  |          || md_type_nid == NID_id_GostR3411_2012_256 | 
					
						
							|  |  |  |          || md_type_nid == NID_id_GostR3411_2012_512) | 
					
						
							|  |  |  |         && !getenv("LEGACY_GOST_PKCS12")) { | 
					
						
							|  |  |  |         md_size = TK26_MAC_KEY_LEN; | 
					
						
							|  |  |  |         if (!pkcs12_gen_gost_mac_key(pass, passlen, salt, saltlen, iter, | 
					
						
							|  |  |  |                                      md_size, key, md_type)) { | 
					
						
							|  |  |  |             PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_KEY_GEN_ERROR); | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |         if (!PKCS12_key_gen(pass, passlen, salt, saltlen, PKCS12_MAC_ID, iter, | 
					
						
							|  |  |  |                             md_size, key, md_type)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_KEY_GEN_ERROR); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     HMAC_CTX_init(&hmac); | 
					
						
							|  |  |  |     if (!HMAC_Init_ex(&hmac, key, md_size, md_type, NULL) | 
					
						
							|  |  |  |         || !HMAC_Update(&hmac, p12->authsafes->d.data->data, | 
					
						
							|  |  |  |                         p12->authsafes->d.data->length) | 
					
						
							|  |  |  |         || !HMAC_Final(&hmac, mac, maclen)) { | 
					
						
							|  |  |  |         HMAC_CTX_cleanup(&hmac); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     HMAC_CTX_cleanup(&hmac); | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Verify the mac */ | 
					
						
							| 
									
										
										
										
											2005-05-11 11:45:39 +08:00
										 |  |  | int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen) | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     unsigned char mac[EVP_MAX_MD_SIZE]; | 
					
						
							|  |  |  |     unsigned int maclen; | 
					
						
							|  |  |  |     if (p12->mac == NULL) { | 
					
						
							|  |  |  |         PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC, PKCS12_R_MAC_ABSENT); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!PKCS12_gen_mac(p12, pass, passlen, mac, &maclen)) { | 
					
						
							|  |  |  |         PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC, PKCS12_R_MAC_GENERATION_ERROR); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((maclen != (unsigned int)p12->mac->dinfo->digest->length) | 
					
						
							| 
									
										
										
										
											2015-05-27 23:12:13 +08:00
										 |  |  |         || CRYPTO_memcmp(mac, p12->mac->dinfo->digest->data, maclen)) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Set a mac */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-11 11:45:39 +08:00
										 |  |  | int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                    unsigned char *salt, int saltlen, int iter, | 
					
						
							|  |  |  |                    const EVP_MD *md_type) | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     unsigned char mac[EVP_MAX_MD_SIZE]; | 
					
						
							|  |  |  |     unsigned int maclen; | 
					
						
							| 
									
										
										
										
											1999-04-23 23:01:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (!md_type) | 
					
						
							|  |  |  |         md_type = EVP_sha1(); | 
					
						
							|  |  |  |     if (PKCS12_setup_mac(p12, iter, salt, saltlen, md_type) == PKCS12_ERROR) { | 
					
						
							|  |  |  |         PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_SETUP_ERROR); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!PKCS12_gen_mac(p12, pass, passlen, mac, &maclen)) { | 
					
						
							|  |  |  |         PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_GENERATION_ERROR); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-03-14 12:16:42 +08:00
										 |  |  |     if (!(ASN1_OCTET_STRING_set(p12->mac->dinfo->digest, mac, maclen))) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_STRING_SET_ERROR); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Set up a mac structure */ | 
					
						
							| 
									
										
										
										
											2005-05-11 11:45:39 +08:00
										 |  |  | int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                      const EVP_MD *md_type) | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-07 01:43:59 +08:00
										 |  |  |     if ((p12->mac = PKCS12_MAC_DATA_new()) == NULL) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return PKCS12_ERROR; | 
					
						
							|  |  |  |     if (iter > 1) { | 
					
						
							| 
									
										
										
										
											2015-05-07 01:43:59 +08:00
										 |  |  |         if ((p12->mac->iter = ASN1_INTEGER_new()) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!ASN1_INTEGER_set(p12->mac->iter, iter)) { | 
					
						
							|  |  |  |             PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!saltlen) | 
					
						
							|  |  |  |         saltlen = PKCS12_SALT_LEN; | 
					
						
							|  |  |  |     p12->mac->salt->length = saltlen; | 
					
						
							| 
									
										
										
										
											2015-05-07 01:43:59 +08:00
										 |  |  |     if ((p12->mac->salt->data = OPENSSL_malloc(saltlen)) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!salt) { | 
					
						
							| 
									
										
										
										
											2015-02-26 19:57:37 +08:00
										 |  |  |         if (RAND_bytes(p12->mac->salt->data, saltlen) <= 0) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             return 0; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |         memcpy(p12->mac->salt->data, salt, saltlen); | 
					
						
							|  |  |  |     p12->mac->dinfo->algor->algorithm = OBJ_nid2obj(EVP_MD_type(md_type)); | 
					
						
							| 
									
										
										
										
											2015-05-07 01:43:59 +08:00
										 |  |  |     if ((p12->mac->dinfo->algor->parameter = ASN1_TYPE_new()) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     p12->mac->dinfo->algor->parameter->type = V_ASN1_NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											1999-03-29 07:17:34 +08:00
										 |  |  | } |