195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * project 1999. 395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */ 495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* ==================================================================== 595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without 895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions 995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met: 1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the above copyright 1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * notice, this list of conditions and the following disclaimer. 1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright 1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * notice, this list of conditions and the following disclaimer in 1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the documentation and/or other materials provided with the 1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * distribution. 1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this 2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * software must display the following acknowledgment: 2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * "This product includes software developed by the OpenSSL Project 2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * endorse or promote products derived from this software without 2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * prior written permission. For written permission, please contact 2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * licensing@OpenSSL.org. 2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 5. Products derived from this software may not be called "OpenSSL" 3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * nor may "OpenSSL" appear in their names without prior written 3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * permission of the OpenSSL Project. 3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 6. Redistributions of any form whatsoever must retain the following 3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * acknowledgment: 3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * "This product includes software developed by the OpenSSL Project 3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OF THE POSSIBILITY OF SUCH DAMAGE. 5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ==================================================================== 5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This product includes cryptographic software written by Eric Young 5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * (eay@cryptsoft.com). This product includes software written by Tim 5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Hudson (tjh@cryptsoft.com). */ 5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/pkcs8.h> 5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 585127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley#include <assert.h> 595127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley#include <limits.h> 605127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/asn1.h> 6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/bn.h> 635127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley#include <openssl/buf.h> 6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/cipher.h> 6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/digest.h> 6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/err.h> 678e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley#include <openssl/hmac.h> 6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/mem.h> 6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/x509.h> 7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 718e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley#include "../bytestring/internal.h" 7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "../evp/internal.h" 7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define PKCS12_KEY_ID 1 7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define PKCS12_IV_ID 2 778e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley#define PKCS12_MAC_ID 3 7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int ascii_to_ucs2(const char *ascii, size_t ascii_len, 80e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin uint8_t **out, size_t *out_len) { 8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley uint8_t *unitmp; 8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t ulen, i; 8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ulen = ascii_len * 2 + 2; 8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (ulen < ascii_len) { 8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unitmp = OPENSSL_malloc(ulen); 8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (unitmp == NULL) { 9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (i = 0; i < ulen - 2; i += 2) { 9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unitmp[i] = 0; 9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unitmp[i + 1] = ascii[i >> 1]; 9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Make result double null terminated */ 9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unitmp[ulen - 2] = 0; 9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unitmp[ulen - 1] = 0; 10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *out_len = ulen; 10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *out = unitmp; 10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 105e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjaminstatic int pkcs12_key_gen_raw(const uint8_t *pass_raw, size_t pass_raw_len, 1068e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley const uint8_t *salt, size_t salt_len, 107e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin int id, int iterations, 10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t out_len, uint8_t *out, 10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const EVP_MD *md_type) { 11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley uint8_t *B, *D, *I, *p, *Ai; 11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int Slen, Plen, Ilen, Ijlen; 11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int i, j, v; 11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t u; 11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int ret = 0; 11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley BIGNUM *Ij, *Bpl1; /* These hold Ij and B + 1 */ 11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_MD_CTX ctx; 11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_MD_CTX_init(&ctx); 11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley v = EVP_MD_block_size(md_type); 12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley u = EVP_MD_size(md_type); 12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley D = OPENSSL_malloc(v); 12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley Ai = OPENSSL_malloc(u); 12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley B = OPENSSL_malloc(v + 1); 12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley Slen = v * ((salt_len + v - 1) / v); 125e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (pass_raw_len) 126e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin Plen = v * ((pass_raw_len + v - 1) / v); 12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley else 12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley Plen = 0; 12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley Ilen = Slen + Plen; 13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley I = OPENSSL_malloc(Ilen); 13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley Ij = BN_new(); 13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley Bpl1 = BN_new(); 13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!D || !Ai || !B || !I || !Ij || !Bpl1) 13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (i = 0; i < v; i++) 13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley D[i] = id; 13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley p = I; 13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (i = 0; i < Slen; i++) 13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *p++ = salt[i % salt_len]; 14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (i = 0; i < Plen; i++) 141e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin *p++ = pass_raw[i % pass_raw_len]; 14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (;;) { 14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!EVP_DigestInit_ex(&ctx, md_type, NULL) || 14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley !EVP_DigestUpdate(&ctx, D, v) || 14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley !EVP_DigestUpdate(&ctx, I, Ilen) || 14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley !EVP_DigestFinal_ex(&ctx, Ai, NULL)) { 14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (j = 1; j < iterations; j++) { 15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!EVP_DigestInit_ex(&ctx, md_type, NULL) || 15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley !EVP_DigestUpdate(&ctx, Ai, u) || 15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley !EVP_DigestFinal_ex(&ctx, Ai, NULL)) { 15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley memcpy(out, Ai, out_len < u ? out_len : u); 15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (u >= out_len) { 15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = 1; 15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto end; 16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley out_len -= u; 16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley out += u; 16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (j = 0; j < v; j++) 16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley B[j] = Ai[j % u]; 16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Work out B + 1 first then can use B as tmp space */ 16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!BN_bin2bn(B, v, Bpl1)) 16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!BN_add_word(Bpl1, 1)) 16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (j = 0; j < Ilen; j += v) { 17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!BN_bin2bn(I + j, v, Ij)) 17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!BN_add(Ij, Ij, Bpl1)) 17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!BN_bn2bin(Ij, B)) 17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 17795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley Ijlen = BN_num_bytes(Ij); 17895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* If more than 2^(v*8) - 1 cut off MSB */ 17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (Ijlen > v) { 18095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!BN_bn2bin(Ij, B)) 18195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 18295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley memcpy(I + j, B + 1, v); 18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* If less than v bytes pad with zeroes */ 18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else if (Ijlen < v) { 18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley memset(I + j, 0, v - Ijlen); 18695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!BN_bn2bin(Ij, I + j + v - Ijlen)) 18795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else if (!BN_bn2bin(Ij, I + j)) { 18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 19095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyerr: 195e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin OPENSSL_PUT_ERROR(PKCS8, pkcs12_key_gen_raw, ERR_R_MALLOC_FAILURE); 19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyend: 19895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(Ai); 19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(B); 20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(D); 20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(I); 20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley BN_free(Ij); 20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley BN_free(Bpl1); 20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_MD_CTX_cleanup(&ctx); 20595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 20695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return ret; 20795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 20895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 209e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjaminstatic int pkcs12_pbe_keyivgen(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw, 210e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin size_t pass_raw_len, ASN1_TYPE *param, 21195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const EVP_CIPHER *cipher, const EVP_MD *md, 21295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int is_encrypt) { 21395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley PBEPARAM *pbe; 21495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int salt_len, iterations, ret; 21595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley uint8_t *salt; 21695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const uint8_t *pbuf; 21795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley uint8_t key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; 21895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 21995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Extract useful info from parameter */ 22095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (param == NULL || param->type != V_ASN1_SEQUENCE || 22195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley param->value.sequence == NULL) { 22295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_DECODE_ERROR); 22395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 22495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 22595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 22695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley pbuf = param->value.sequence->data; 22795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length); 22895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (pbe == NULL) { 22995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_DECODE_ERROR); 23095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 23195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 23295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 23395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!pbe->iter) { 23495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley iterations = 1; 23595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 23695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley iterations = ASN1_INTEGER_get(pbe->iter); 23795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 23895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley salt = pbe->salt->data; 23995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley salt_len = pbe->salt->length; 240e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (!pkcs12_key_gen_raw(pass_raw, pass_raw_len, salt, salt_len, PKCS12_KEY_ID, 24195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley iterations, EVP_CIPHER_key_length(cipher), key, md)) { 24295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_KEY_GEN_ERROR); 24395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley PBEPARAM_free(pbe); 24495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 24595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 246e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (!pkcs12_key_gen_raw(pass_raw, pass_raw_len, salt, salt_len, PKCS12_IV_ID, 24795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley iterations, EVP_CIPHER_iv_length(cipher), iv, md)) { 24895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_KEY_GEN_ERROR); 24995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley PBEPARAM_free(pbe); 25095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 25195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 25295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley PBEPARAM_free(pbe); 25395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, is_encrypt); 25495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH); 25595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH); 25695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return ret; 25795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 25895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 259e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamintypedef int (*keygen_func)(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw, 260e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin size_t pass_raw_len, ASN1_TYPE *param, 26195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const EVP_CIPHER *cipher, const EVP_MD *md, 26295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int is_encrypt); 26395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystruct pbe_suite { 26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int pbe_nid; 2668e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley const EVP_CIPHER* (*cipher_func)(); 2678e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley const EVP_MD* (*md_func)(); 26895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley keygen_func keygen; 26995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}; 27095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 27195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic const struct pbe_suite kBuiltinPBE[] = { 27295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley { 2738e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc, EVP_sha1, pkcs12_pbe_keyivgen, 2748e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley }, 2758e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley { 2768e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley NID_pbe_WithSHA1And128BitRC4, EVP_rc4, EVP_sha1, pkcs12_pbe_keyivgen, 27795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley }, 27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley { 2798e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley NID_pbe_WithSHA1And3_Key_TripleDES_CBC, EVP_des_ede3_cbc, EVP_sha1, 28095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley pkcs12_pbe_keyivgen, 28195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley }, 28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}; 28395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 284e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjaminstatic int pbe_cipher_init(ASN1_OBJECT *pbe_obj, 285e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin const uint8_t *pass_raw, size_t pass_raw_len, 286e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin ASN1_TYPE *param, 28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_CIPHER_CTX *ctx, int is_encrypt) { 28895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const EVP_CIPHER *cipher; 28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const EVP_MD *md; 29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unsigned i; 29195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const struct pbe_suite *suite = NULL; 29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const int pbe_nid = OBJ_obj2nid(pbe_obj); 29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (i = 0; i < sizeof(kBuiltinPBE) / sizeof(struct pbe_suite); i++) { 2968e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (kBuiltinPBE[i].pbe_nid == pbe_nid) { 2978e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley suite = &kBuiltinPBE[i]; 29895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley break; 29995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 30095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 30195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 30295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (suite == NULL) { 30395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley char obj_str[80]; 30495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_ALGORITHM); 30595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!pbe_obj) { 30695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley strncpy(obj_str, "NULL", sizeof(obj_str)); 30795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 30895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley i2t_ASN1_OBJECT(obj_str, sizeof(obj_str), pbe_obj); 30995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ERR_add_error_data(2, "TYPE=", obj_str); 31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 31295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 31395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 3148e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (suite->cipher_func == NULL) { 31595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley cipher = NULL; 31695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 3178e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley cipher = suite->cipher_func(); 31895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!cipher) { 31995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_CIPHER); 32095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 32195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 32295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 32395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 3248e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (suite->md_func == NULL) { 32595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley md = NULL; 32695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 3278e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley md = suite->md_func(); 32895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!md) { 32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_DIGEST); 33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 33195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 334e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (!suite->keygen(ctx, pass_raw, pass_raw_len, param, cipher, md, 335e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin is_encrypt)) { 33695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_KEYGEN_FAILURE); 33795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 33895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 33995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 34095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 34195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 34295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 343e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjaminstatic int pbe_crypt(const X509_ALGOR *algor, 344e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin const uint8_t *pass_raw, size_t pass_raw_len, 3458e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley const uint8_t *in, size_t in_len, 3468e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley uint8_t **out, size_t *out_len, 34795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int is_encrypt) { 34895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley uint8_t *buf; 34995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int n, ret = 0; 35095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_CIPHER_CTX ctx; 35195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unsigned block_size; 35295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 35395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_CIPHER_CTX_init(&ctx); 35495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 355e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (!pbe_cipher_init(algor->algorithm, pass_raw, pass_raw_len, 356e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin algor->parameter, &ctx, is_encrypt)) { 35795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, PKCS8_R_UNKNOWN_CIPHER_ALGORITHM); 35895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 35995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 36095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley block_size = EVP_CIPHER_CTX_block_size(&ctx); 36195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 36295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (in_len + block_size < in_len) { 36395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, PKCS8_R_TOO_LONG); 36495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 36595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 36695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 36795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley buf = OPENSSL_malloc(in_len + block_size); 36895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (buf == NULL) { 36995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, ERR_R_MALLOC_FAILURE); 37095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 37195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 37295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 37395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!EVP_CipherUpdate(&ctx, buf, &n, in, in_len)) { 37495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(buf); 37595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, ERR_R_EVP_LIB); 37695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 37795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 37895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *out_len = n; 37995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 38095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!EVP_CipherFinal_ex(&ctx, buf + n, &n)) { 38195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(buf); 38295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, ERR_R_EVP_LIB); 38395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 38495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 38595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *out_len += n; 38695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *out = buf; 38795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = 1; 38895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 38995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyerr: 39095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_CIPHER_CTX_cleanup(&ctx); 39195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return ret; 39295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 39395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 39495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void *pkcs12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it, 395e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin const uint8_t *pass_raw, 396e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin size_t pass_raw_len, 39795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ASN1_OCTET_STRING *oct) { 39895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley uint8_t *out; 39995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const uint8_t *p; 40095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley void *ret; 40195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t out_len; 40295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 403e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (!pbe_crypt(algor, pass_raw, pass_raw_len, oct->data, oct->length, 404e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin &out, &out_len, 0 /* decrypt */)) { 40595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_decrypt_d2i, PKCS8_R_CRYPT_ERROR); 40695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return NULL; 40795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 40895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley p = out; 40995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = ASN1_item_d2i(NULL, &p, out_len, it); 41095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_cleanse(out, out_len); 41195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!ret) { 41295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_decrypt_d2i, PKCS8_R_DECODE_ERROR); 41395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 41495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(out); 41595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return ret; 41695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 41795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 41895c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyPKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, const char *pass, 41995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int pass_len) { 420e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin uint8_t *pass_raw = NULL; 421e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin size_t pass_raw_len = 0; 422e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin PKCS8_PRIV_KEY_INFO *ret; 423e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin 424e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (pass) { 425e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (pass_len == -1) { 426e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin pass_len = strlen(pass); 427e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin } 428e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (!ascii_to_ucs2(pass, pass_len, &pass_raw, &pass_raw_len)) { 429e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin OPENSSL_PUT_ERROR(PKCS8, pkcs12_key_gen_asc, PKCS8_R_DECODE_ERROR); 430e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin return NULL; 431e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin } 43295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 433e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin 434e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin ret = PKCS8_decrypt_pbe(pkcs8, pass_raw, pass_raw_len); 435e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin 436e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (pass_raw) { 437e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin OPENSSL_cleanse(pass_raw, pass_raw_len); 438e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin OPENSSL_free(pass_raw); 439e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin } 440e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin return ret; 441e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin} 442e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin 443e216d6bb9f9139656e1d0c6b6312787fc2e596f9David BenjaminPKCS8_PRIV_KEY_INFO *PKCS8_decrypt_pbe(X509_SIG *pkcs8, const uint8_t *pass_raw, 444e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin size_t pass_raw_len) { 44595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return pkcs12_item_decrypt_d2i(pkcs8->algor, 446e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass_raw, 447e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin pass_raw_len, pkcs8->digest); 44895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 44995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 45095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic ASN1_OCTET_STRING *pkcs12_item_i2d_encrypt(X509_ALGOR *algor, 45195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const ASN1_ITEM *it, 452e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin const uint8_t *pass_raw, 453e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin size_t pass_raw_len, void *obj) { 45495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ASN1_OCTET_STRING *oct; 45595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley uint8_t *in = NULL; 45695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int in_len; 45795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t crypt_len; 45895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 45995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley oct = M_ASN1_OCTET_STRING_new(); 46095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (oct == NULL) { 46195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_i2d_encrypt, ERR_R_MALLOC_FAILURE); 46295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return NULL; 46395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 46495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley in_len = ASN1_item_i2d(obj, &in, it); 46595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!in) { 46695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_i2d_encrypt, PKCS8_R_ENCODE_ERROR); 46795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return NULL; 46895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 469e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (!pbe_crypt(algor, pass_raw, pass_raw_len, in, in_len, &oct->data, &crypt_len, 47095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 1 /* encrypt */)) { 47195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_i2d_encrypt, PKCS8_R_ENCRYPT_ERROR); 47295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(in); 47395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return NULL; 47495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 47595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley oct->length = crypt_len; 47695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_cleanse(in, in_len); 47795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(in); 47895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return oct; 47995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 48095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 48195c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyX509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass, 48295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int pass_len, uint8_t *salt, size_t salt_len, 48395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int iterations, PKCS8_PRIV_KEY_INFO *p8inf) { 484e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin uint8_t *pass_raw = NULL; 485e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin size_t pass_raw_len = 0; 486e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin X509_SIG *ret; 48795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 488e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (pass) { 489e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (pass_len == -1) { 490e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin pass_len = strlen(pass); 491e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin } 492e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (!ascii_to_ucs2(pass, pass_len, &pass_raw, &pass_raw_len)) { 493e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin OPENSSL_PUT_ERROR(PKCS8, pkcs12_key_gen_asc, PKCS8_R_DECODE_ERROR); 494e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin return NULL; 495e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin } 49695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 49795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 498e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin ret = PKCS8_encrypt_pbe(pbe_nid, pass_raw, pass_raw_len, 499e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin salt, salt_len, iterations, p8inf); 500e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin 501e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin if (pass_raw) { 502e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin OPENSSL_cleanse(pass_raw, pass_raw_len); 503e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin OPENSSL_free(pass_raw); 504e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin } 505e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin return ret; 506e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin} 507e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin 508e216d6bb9f9139656e1d0c6b6312787fc2e596f9David BenjaminX509_SIG *PKCS8_encrypt_pbe(int pbe_nid, 509e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin const uint8_t *pass_raw, size_t pass_raw_len, 510e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin uint8_t *salt, size_t salt_len, 511e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin int iterations, PKCS8_PRIV_KEY_INFO *p8inf) { 512e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin X509_SIG *pkcs8 = NULL; 513e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin X509_ALGOR *pbe; 514e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin 51595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley pkcs8 = X509_SIG_new(); 51695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (pkcs8 == NULL) { 517e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin OPENSSL_PUT_ERROR(PKCS8, PKCS8_encrypt_pbe, ERR_R_MALLOC_FAILURE); 51895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 51995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 52095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 521e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin pbe = PKCS5_pbe_set(pbe_nid, iterations, salt, salt_len); 52295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!pbe) { 523e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin OPENSSL_PUT_ERROR(PKCS8, PKCS8_encrypt_pbe, ERR_R_ASN1_LIB); 52495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 52595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 52695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 52795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley X509_ALGOR_free(pkcs8->algor); 52895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley pkcs8->algor = pbe; 52995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley M_ASN1_OCTET_STRING_free(pkcs8->digest); 53095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley pkcs8->digest = pkcs12_item_i2d_encrypt( 531e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass_raw, pass_raw_len, p8inf); 53295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!pkcs8->digest) { 533e216d6bb9f9139656e1d0c6b6312787fc2e596f9David Benjamin OPENSSL_PUT_ERROR(PKCS8, PKCS8_encrypt_pbe, PKCS8_R_ENCRYPT_ERROR); 53495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 53595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 53695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 53795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return pkcs8; 53895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 53995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyerr: 54095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley X509_SIG_free(pkcs8); 54195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return NULL; 54295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 54395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 54495c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyEVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) { 54595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_PKEY *pkey = NULL; 54695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ASN1_OBJECT *algoid; 54795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley char obj_tmp[80]; 54895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 54995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8)) 55095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return NULL; 55195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 55295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley pkey = EVP_PKEY_new(); 55395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (pkey == NULL) { 55495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY, ERR_R_MALLOC_FAILURE); 55595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return NULL; 55695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 55795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 55895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) { 55995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY, 56095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); 56195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley i2t_ASN1_OBJECT(obj_tmp, 80, algoid); 56295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ERR_add_error_data(2, "TYPE=", obj_tmp); 56395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto error; 56495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 56595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 56695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (pkey->ameth->priv_decode) { 56795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!pkey->ameth->priv_decode(pkey, p8)) { 56895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY, PKCS8_R_PRIVATE_KEY_DECODE_ERROR); 56995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto error; 57095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 57195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 57295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY, PKCS8_R_METHOD_NOT_SUPPORTED); 57395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto error; 57495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 57595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 57695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return pkey; 57795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 57895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyerror: 57995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_PKEY_free(pkey); 58095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return NULL; 58195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 58295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 58395c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyPKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) { 58495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley PKCS8_PRIV_KEY_INFO *p8; 58595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 58695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley p8 = PKCS8_PRIV_KEY_INFO_new(); 58795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (p8 == NULL) { 58895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); 58995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return NULL; 59095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 59195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley p8->broken = PKCS8_OK; 59295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 59395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (pkey->ameth) { 59495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (pkey->ameth->priv_encode) { 59595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!pkey->ameth->priv_encode(p8, pkey)) { 59695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8, 59795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley PKCS8_R_PRIVATE_KEY_ENCODE_ERROR); 59895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto error; 59995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 60095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 60195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8, PKCS8_R_METHOD_NOT_SUPPORTED); 60295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto error; 60395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 60495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 60595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8, 60695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); 60795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto error; 60895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 60995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return p8; 61095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 61195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyerror: 61295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley PKCS8_PRIV_KEY_INFO_free(p8); 61395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return NULL; 61495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 6158e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6168e16b6e6582810de46b4db7926a2462be8e789d2Adam Langleystruct pkcs12_context { 6178e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley EVP_PKEY **out_key; 6188e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley STACK_OF(X509) *out_certs; 6198e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley uint8_t *password; 6208e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley size_t password_len; 6218e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley}; 6228e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6238e16b6e6582810de46b4db7926a2462be8e789d2Adam Langleystatic int PKCS12_handle_content_info(CBS *content_info, unsigned depth, 6248e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley struct pkcs12_context *ctx); 6258e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6268e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley/* PKCS12_handle_content_infos parses a series of PKCS#7 ContentInfos in a 6278e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * SEQUENCE. */ 6288e16b6e6582810de46b4db7926a2462be8e789d2Adam Langleystatic int PKCS12_handle_content_infos(CBS *content_infos, 6298e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley unsigned depth, 6308e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley struct pkcs12_context *ctx) { 6318e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley uint8_t *der_bytes = NULL; 6328e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley size_t der_len; 6338e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS in; 6348e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley int ret = 0; 6358e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6368e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* Generally we only expect depths 0 (the top level, with a 6378e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * pkcs7-encryptedData and a pkcs7-data) and depth 1 (the various PKCS#12 6388e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * bags). */ 6398e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (depth > 3) { 6408e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos, 6418e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_PKCS12_TOO_DEEPLY_NESTED); 6428e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley return 0; 6438e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 6448e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6458e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* Although a BER->DER conversion is done at the beginning of |PKCS12_parse|, 6468e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * the ASN.1 data gets wrapped in OCTETSTRINGs and/or encrypted and the 6478e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * conversion cannot see through those wrappings. So each time we step 6488e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * through one we need to convert to DER again. */ 6498e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_asn1_ber_to_der(content_infos, &der_bytes, &der_len)) { 6508e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley return 0; 6518e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 6528e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6538e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (der_bytes != NULL) { 6548e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_init(&in, der_bytes, der_len); 6558e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } else { 6568e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_init(&in, CBS_data(content_infos), CBS_len(content_infos)); 6578e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 6588e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6598e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(&in, &in, CBS_ASN1_SEQUENCE)) { 6608e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos, 6618e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_BAD_PKCS12_DATA); 6628e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 6638e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 6648e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6658e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley while (CBS_len(&in) > 0) { 6668e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS content_info; 6678e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE)) { 6688e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos, 6698e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_BAD_PKCS12_DATA); 6708e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 6718e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 6728e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6738e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!PKCS12_handle_content_info(&content_info, depth + 1, ctx)) { 6748e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 6758e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 6768e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 6778e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6788e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* NSS includes additional data after the SEQUENCE, but it's an (unwrapped) 6798e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * copy of the same encrypted private key (with the same IV and 6808e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * ciphertext)! */ 6818e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6828e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley ret = 1; 6838e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6848e16b6e6582810de46b4db7926a2462be8e789d2Adam Langleyerr: 6858e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (der_bytes != NULL) { 6868e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_free(der_bytes); 6878e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 6888e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley return ret; 6898e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley} 6908e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6918e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a 6928e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * PKCS#12 structure. */ 6938e16b6e6582810de46b4db7926a2462be8e789d2Adam Langleystatic int PKCS12_handle_content_info(CBS *content_info, unsigned depth, 6948e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley struct pkcs12_context *ctx) { 6958e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS content_type, wrapped_contents, contents, content_infos; 6968e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley int nid, ret = 0; 6978e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 6988e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) || 6998e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(content_info, &wrapped_contents, 7008e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { 7018e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA); 7028e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 7038e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 7048e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 7058e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley nid = OBJ_cbs2nid(&content_type); 7068e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (nid == NID_pkcs7_encrypted) { 7078e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* See https://tools.ietf.org/html/rfc2315#section-13. 7088e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * 7098e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * PKCS#7 encrypted data inside a PKCS#12 structure is generally an 7108e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * encrypted certificate bag and it's generally encrypted with 40-bit 7118e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * RC2-CBC. */ 71258f90951eb8d4393925d3155a69be49236816f82Adam Langley CBS version_bytes, eci, contents_type, ai, encrypted_contents; 7138e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509_ALGOR *algor = NULL; 7148e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley const uint8_t *inp; 7158e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley uint8_t *out; 7168e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley size_t out_len; 7178e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 7188e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) || 7198e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) || 7208e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* EncryptedContentInfo, see 7218e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * https://tools.ietf.org/html/rfc2315#section-10.1 */ 7228e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) || 7238e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) || 7248e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* AlgorithmIdentifier, see 7258e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */ 72658f90951eb8d4393925d3155a69be49236816f82Adam Langley !CBS_get_asn1_element(&eci, &ai, CBS_ASN1_SEQUENCE) || 72758f90951eb8d4393925d3155a69be49236816f82Adam Langley !CBS_get_asn1(&eci, &encrypted_contents, 72858f90951eb8d4393925d3155a69be49236816f82Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | 0)) { 7298e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, 7308e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_BAD_PKCS12_DATA); 7318e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 7328e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 7338e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 7348e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (OBJ_cbs2nid(&contents_type) != NID_pkcs7_data) { 7358e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, 7368e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_BAD_PKCS12_DATA); 7378e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 7388e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 7398e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 7408e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley inp = CBS_data(&ai); 7418e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley algor = d2i_X509_ALGOR(NULL, &inp, CBS_len(&ai)); 7428e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (algor == NULL) { 7438e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 7448e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 7458e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (inp != CBS_data(&ai) + CBS_len(&ai)) { 7468e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509_ALGOR_free(algor); 7478e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, 7488e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_BAD_PKCS12_DATA); 7498e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 7508e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 7518e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 7528e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!pbe_crypt(algor, ctx->password, ctx->password_len, 7538e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_data(&encrypted_contents), CBS_len(&encrypted_contents), 7548e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley &out, &out_len, 0 /* decrypt */)) { 7558e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509_ALGOR_free(algor); 7568e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 7578e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 7588e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509_ALGOR_free(algor); 7598e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 7608e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_init(&content_infos, out, out_len); 7618e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley ret = PKCS12_handle_content_infos(&content_infos, depth + 1, ctx); 7628e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_free(out); 7638e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } else if (nid == NID_pkcs7_data) { 7648e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS octet_string_contents; 7658e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 7668e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents, 7678e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_ASN1_OCTETSTRING)) { 7688e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, 7698e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_BAD_PKCS12_DATA); 7708e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 7718e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 7728e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 7738e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley ret = PKCS12_handle_content_infos(&octet_string_contents, depth + 1, ctx); 7748e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } else if (nid == NID_pkcs8ShroudedKeyBag) { 7758e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section 7768e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * 4.2.2. */ 7778e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley const uint8_t *inp = CBS_data(&wrapped_contents); 7788e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_PRIV_KEY_INFO *pki = NULL; 7798e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509_SIG *encrypted = NULL; 7808e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 7818e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (*ctx->out_key) { 7828e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, 7838e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12); 7848e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 7858e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 7868e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 7878e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* encrypted isn't actually an X.509 signature, but it has the same 7888e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * structure as one and so |X509_SIG| is reused to store it. */ 7898e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley encrypted = d2i_X509_SIG(NULL, &inp, CBS_len(&wrapped_contents)); 7908e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (encrypted == NULL) { 7918e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, 7928e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_BAD_PKCS12_DATA); 7938e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 7948e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 7958e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (inp != CBS_data(&wrapped_contents) + CBS_len(&wrapped_contents)) { 7968e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, 7978e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_BAD_PKCS12_DATA); 7988e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509_SIG_free(encrypted); 7998e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 8008e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8018e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8028e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley pki = PKCS8_decrypt_pbe(encrypted, ctx->password, ctx->password_len); 8038e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509_SIG_free(encrypted); 8048e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (pki == NULL) { 8058e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 8068e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8078e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8088e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley *ctx->out_key = EVP_PKCS82PKEY(pki); 8098e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_PRIV_KEY_INFO_free(pki); 8108e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8118e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (ctx->out_key == NULL) { 8128e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 8138e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8148e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley ret = 1; 8158e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } else if (nid == NID_certBag) { 8168e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS cert_bag, cert_type, wrapped_cert, cert; 8178e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8188e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(&wrapped_contents, &cert_bag, CBS_ASN1_SEQUENCE) || 8198e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) || 8208e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(&cert_bag, &wrapped_cert, 8218e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || 8228e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) { 8238e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, 8248e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_BAD_PKCS12_DATA); 8258e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 8268e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8278e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8288e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (OBJ_cbs2nid(&cert_type) == NID_x509Certificate) { 8298e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley const uint8_t *inp = CBS_data(&cert); 8308e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509 *x509 = d2i_X509(NULL, &inp, CBS_len(&cert)); 8318e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!x509) { 8328e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, 8338e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_BAD_PKCS12_DATA); 8348e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 8358e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8368e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (inp != CBS_data(&cert) + CBS_len(&cert)) { 8378e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, 8388e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_BAD_PKCS12_DATA); 8398e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509_free(x509); 8408e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 8418e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8428e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8438e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (0 == sk_X509_push(ctx->out_certs, x509)) { 8448e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509_free(x509); 8458e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 8468e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8478e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8488e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley ret = 1; 8498e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } else { 8508e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* Unknown element type - ignore it. */ 8518e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley ret = 1; 8528e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8538e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8548e16b6e6582810de46b4db7926a2462be8e789d2Adam Langleyerr: 8558e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley return ret; 8568e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley} 8578e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8588e16b6e6582810de46b4db7926a2462be8e789d2Adam Langleyint PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs, 8598e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS *ber_in, const char *password) { 8608e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley uint8_t *der_bytes = NULL; 8618e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley size_t der_len; 8628e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS in, pfx, mac_data, authsafe, content_type, wrapped_authsafes, authsafes; 8638e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley uint64_t version; 8648e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley int ret = 0; 8658e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley struct pkcs12_context ctx; 8668e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley const size_t original_out_certs_len = sk_X509_num(out_certs); 8678e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8688e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* The input may be in BER format. */ 8698e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_asn1_ber_to_der(ber_in, &der_bytes, &der_len)) { 8708e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley return 0; 8718e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8728e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (der_bytes != NULL) { 8738e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_init(&in, der_bytes, der_len); 8748e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } else { 8758e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_init(&in, CBS_data(ber_in), CBS_len(ber_in)); 8768e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8778e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8788e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley *out_key = NULL; 8798e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley memset(&ctx, 0, sizeof(ctx)); 8808e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8818e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section 8828e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * four. */ 8838e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(&in, &pfx, CBS_ASN1_SEQUENCE) || 8845127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley CBS_len(&in) != 0 || 8858e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1_uint64(&pfx, &version)) { 8868e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA); 8878e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 8888e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8898e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8908e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (version < 3) { 8918e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_VERSION); 8928e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 8938e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8948e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 8958e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(&pfx, &authsafe, CBS_ASN1_SEQUENCE)) { 8968e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA); 8978e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 8988e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 8998e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9008e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (CBS_len(&pfx) == 0) { 9018e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_MISSING_MAC); 9028e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9038e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9048e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9058e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE)) { 9068e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA); 9078e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9088e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9098e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9108e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* authsafe is a PKCS#7 ContentInfo. See 9118e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * https://tools.ietf.org/html/rfc2315#section-7. */ 9128e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(&authsafe, &content_type, CBS_ASN1_OBJECT) || 9138e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(&authsafe, &wrapped_authsafes, 9148e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { 9158e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA); 9168e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9178e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9188e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9198e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* The content type can either be |NID_pkcs7_data| or |NID_pkcs7_signed|. The 9208e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * latter indicates that it's signed by a public key, which isn't 9218e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley * supported. */ 9228e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (OBJ_cbs2nid(&content_type) != NID_pkcs7_data) { 9238e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, 9248e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED); 9258e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9268e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9278e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9288e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(&wrapped_authsafes, &authsafes, CBS_ASN1_OCTETSTRING)) { 9298e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA); 9308e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9318e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9328e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9338e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley ctx.out_key = out_key; 9348e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley ctx.out_certs = out_certs; 9358e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!ascii_to_ucs2(password, strlen(password), &ctx.password, 9368e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley &ctx.password_len)) { 9378e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_DECODE_ERROR); 9388e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9398e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9408e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9418e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* Verify the MAC. */ 9428e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley { 9438e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS mac, hash_type_seq, hash_oid, salt, expected_mac; 9448e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley uint64_t iterations; 9458e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley int hash_nid; 9468e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley const EVP_MD *md; 9478e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley uint8_t hmac_key[EVP_MAX_MD_SIZE]; 9488e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley uint8_t hmac[EVP_MAX_MD_SIZE]; 9498e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley unsigned hmac_len; 9508e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9518e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1(&mac_data, &mac, CBS_ASN1_SEQUENCE) || 9528e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(&mac, &hash_type_seq, CBS_ASN1_SEQUENCE) || 9538e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(&hash_type_seq, &hash_oid, CBS_ASN1_OBJECT) || 9548e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(&mac, &expected_mac, CBS_ASN1_OCTETSTRING) || 9558e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley !CBS_get_asn1(&mac_data, &salt, CBS_ASN1_OCTETSTRING)) { 9568e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA); 9578e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9588e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9598e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9608e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* The iteration count is optional and the default is one. */ 9618e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley iterations = 1; 9628e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (CBS_len(&mac_data) > 0) { 9638e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_get_asn1_uint64(&mac_data, &iterations) || 9648e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley iterations > INT_MAX) { 9658e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA); 9668e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9678e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9688e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9698e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9708e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley hash_nid = OBJ_cbs2nid(&hash_oid); 9718e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (hash_nid == NID_undef || 9728e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley (md = EVP_get_digestbynid(hash_nid)) == NULL) { 9738e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_UNKNOWN_HASH); 9748e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9758e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9768e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9778e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!pkcs12_key_gen_raw(ctx.password, ctx.password_len, CBS_data(&salt), 9788e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_len(&salt), PKCS12_MAC_ID, iterations, 9798e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley EVP_MD_size(md), hmac_key, md)) { 9808e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9818e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9828e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9838e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (NULL == HMAC(md, hmac_key, EVP_MD_size(md), CBS_data(&authsafes), 9848e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley CBS_len(&authsafes), hmac, &hmac_len)) { 9858e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9868e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9878e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9888e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!CBS_mem_equal(&expected_mac, hmac, hmac_len)) { 9898e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_INCORRECT_PASSWORD); 9908e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9918e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9928e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9938e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9948e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley /* authsafes contains a series of PKCS#7 ContentInfos. */ 9958e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!PKCS12_handle_content_infos(&authsafes, 0, &ctx)) { 9968e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley goto err; 9978e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 9988e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 9998e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley ret = 1; 10008e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 10018e16b6e6582810de46b4db7926a2462be8e789d2Adam Langleyerr: 10028e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (ctx.password) { 10038e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_free(ctx.password); 10048e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 10058e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (der_bytes) { 10068e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley OPENSSL_free(der_bytes); 10078e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 10088e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (!ret) { 10098e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley if (*out_key) { 10108e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley EVP_PKEY_free(*out_key); 10118e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley *out_key = NULL; 10128e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 10138e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley while (sk_X509_num(out_certs) > original_out_certs_len) { 10148e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509 *x509 = sk_X509_pop(out_certs); 10158e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley X509_free(x509); 10168e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 10178e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley } 10188e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley 10198e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley return ret; 10208e16b6e6582810de46b4db7926a2462be8e789d2Adam Langley} 1021bed8ce78f001c600a143966b932f8e587c35e573Adam Langley 1022bed8ce78f001c600a143966b932f8e587c35e573Adam Langleyvoid PKCS12_PBE_add(){}; 10235127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10245127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langleystruct pkcs12_st { 10255127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley uint8_t *ber_bytes; 10265127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley size_t ber_len; 10275127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley}; 10285127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10295127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam LangleyPKCS12* d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes, size_t ber_len) { 10305127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley PKCS12 *p12; 10315127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10325127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley /* out_p12 must be NULL because we don't export the PKCS12 structure. */ 10335127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley assert(out_p12 == NULL); 10345127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10355127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley p12 = OPENSSL_malloc(sizeof(PKCS12)); 10365127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (!p12) { 10375127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley return NULL; 10385127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 10395127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10405127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley p12->ber_bytes = OPENSSL_malloc(ber_len); 10415127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (!p12->ber_bytes) { 10425127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley OPENSSL_free(p12); 10435127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley return NULL; 10445127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 10455127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10465127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley memcpy(p12->ber_bytes, *ber_bytes, ber_len); 10475127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley p12->ber_len = ber_len; 10485127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley *ber_bytes += ber_len; 10495127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10505127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley return p12; 10515127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley} 10525127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10535127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam LangleyPKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12) { 10545127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley size_t used = 0; 10555127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley BUF_MEM *buf; 10565127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley const uint8_t *dummy; 10575127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley static const size_t kMaxSize = 256 * 1024; 10585127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley PKCS12 *ret = NULL; 10595127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10605127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley buf = BUF_MEM_new(); 10615127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (buf == NULL) { 10625127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley return NULL; 10635127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 10645127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (BUF_MEM_grow(buf, 8192) == 0) { 10655127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley goto out; 10665127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 10675127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10685127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley for (;;) { 10695127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley int n = BIO_read(bio, &buf->data[used], buf->length - used); 10705127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (n < 0) { 10715127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley goto out; 10725127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 10735127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10745127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (n == 0) { 10755127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley break; 10765127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 10775127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley used += n; 10785127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10795127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (used < buf->length) { 10805127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley continue; 10815127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 10825127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10835127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (buf->length > kMaxSize || 10845127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley BUF_MEM_grow(buf, buf->length * 2) == 0) { 10855127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley goto out; 10865127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 10875127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 10885127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10895127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley dummy = (uint8_t*) buf->data; 10905127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley ret = d2i_PKCS12(out_p12, &dummy, used); 10915127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10925127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langleyout: 10935127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley BUF_MEM_free(buf); 10945127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley return ret; 10955127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley} 10965127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 10975127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam LangleyPKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12) { 10985127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley BIO *bio; 10995127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley PKCS12 *ret; 11005127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 11015127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley bio = BIO_new_fp(fp, 0 /* don't take ownership */); 11025127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (!bio) { 11035127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley return NULL; 11045127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 11055127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 11065127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley ret = d2i_PKCS12_bio(bio, out_p12); 11075127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley BIO_free(bio); 11085127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley return ret; 11095127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley} 11105127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 11115127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langleyint PKCS12_parse(const PKCS12 *p12, const char *password, EVP_PKEY **out_pkey, 11125127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley X509 **out_cert, STACK_OF(X509) **out_ca_certs) { 11135127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley CBS ber_bytes; 11145127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley STACK_OF(X509) *ca_certs = NULL; 11155127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley char ca_certs_alloced = 0; 11165127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 11175127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (out_ca_certs != NULL && *out_ca_certs != NULL) { 11185127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley ca_certs = *out_ca_certs; 11195127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 11205127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 11215127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (!ca_certs) { 11225127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley ca_certs = sk_X509_new_null(); 11235127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (ca_certs == NULL) { 11245127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley return 0; 11255127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 11265127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley ca_certs_alloced = 1; 11275127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 11285127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 11295127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley CBS_init(&ber_bytes, p12->ber_bytes, p12->ber_len); 11305127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (!PKCS12_get_key_and_certs(out_pkey, ca_certs, &ber_bytes, password)) { 11315127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (ca_certs_alloced) { 11325127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley sk_X509_free(ca_certs); 11335127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 11345127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley return 0; 11355127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 11365127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 11375127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley *out_cert = NULL; 11385127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (sk_X509_num(ca_certs) > 0) { 11395127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley *out_cert = sk_X509_shift(ca_certs); 11405127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 11415127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 11425127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley if (out_ca_certs) { 11435127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley *out_ca_certs = ca_certs; 11445127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } else { 11455127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley sk_X509_pop_free(ca_certs, X509_free); 11465127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley } 11475127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 11485127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley return 1; 11495127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley} 11505127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley 11515127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langleyvoid PKCS12_free(PKCS12 *p12) { 11525127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley OPENSSL_free(p12->ber_bytes); 11535127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley OPENSSL_free(p12); 11545127db3b4d59066126a1f8c8f7fdf4841a8c58b9Adam Langley} 1155