pkcs8.c revision 69939df2891f62f7f00ff2ac275f1cd81a67454c
1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * project 1999. 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */ 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ==================================================================== 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met: 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the above copyright 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer. 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer in 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the documentation and/or other materials provided with the 17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * distribution. 18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this 20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * software must display the following acknowledgment: 21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software developed by the OpenSSL Project 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * endorse or promote products derived from this software without 26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * prior written permission. For written permission, please contact 27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * licensing@OpenSSL.org. 28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5. Products derived from this software may not be called "OpenSSL" 30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * nor may "OpenSSL" appear in their names without prior written 31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * permission of the OpenSSL Project. 32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 6. Redistributions of any form whatsoever must retain the following 34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * acknowledgment: 35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software developed by the OpenSSL Project 36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE. 50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ==================================================================== 51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This product includes cryptographic software written by Eric Young 53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (eay@cryptsoft.com). This product includes software written by Tim 54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Hudson (tjh@cryptsoft.com). */ 55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/pkcs8.h> 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <assert.h> 59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <limits.h> 60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h> 61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/asn1.h> 63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/buf.h> 644969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin#include <openssl/bytestring.h> 65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/cipher.h> 66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/digest.h> 67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/hmac.h> 69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h> 704969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin#include <openssl/obj.h> 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/x509.h> 72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 73b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include "internal.h" 74f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include "../internal.h" 75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "../bytestring/internal.h" 76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define PKCS12_KEY_ID 1 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define PKCS12_IV_ID 2 80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define PKCS12_MAC_ID 3 81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 82d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int ascii_to_ucs2(const char *ascii, size_t ascii_len, 83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t **out, size_t *out_len) { 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *unitmp; 85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t ulen, i; 86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ulen = ascii_len * 2 + 2; 88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ulen < ascii_len) { 89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unitmp = OPENSSL_malloc(ulen); 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (unitmp == NULL) { 93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (i = 0; i < ulen - 2; i += 2) { 96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unitmp[i] = 0; 97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unitmp[i + 1] = ascii[i >> 1]; 98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Make result double null terminated */ 101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unitmp[ulen - 2] = 0; 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unitmp[ulen - 1] = 0; 103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *out_len = ulen; 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *out = unitmp; 105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int pkcs12_key_gen_raw(const uint8_t *pass_raw, size_t pass_raw_len, 109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *salt, size_t salt_len, 1104969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin uint8_t id, int iterations, 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t out_len, uint8_t *out, 1124969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin const EVP_MD *md) { 1134969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin /* See https://tools.ietf.org/html/rfc7292#appendix-B. Quoted parts of the 1144969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * specification have errata applied and other typos fixed. */ 115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1164969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (iterations < 1) { 1174969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT); 1184969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin return 0; 119e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 1204969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1214969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin /* In the spec, |block_size| is called "v", but measured in bits. */ 1224969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin size_t block_size = EVP_MD_block_size(md); 1234969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1244969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin /* 1. Construct a string, D (the "diversifier"), by concatenating v/8 copies 1254969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * of ID. */ 1264969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin uint8_t D[EVP_MAX_MD_BLOCK_SIZE]; 12769939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan OPENSSL_memset(D, id, block_size); 1284969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1294969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin /* 2. Concatenate copies of the salt together to create a string S of length 1304969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * v(ceiling(s/v)) bits (the final copy of the salt may be truncated to 1314969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * create S). Note that if the salt is the empty string, then so is S. 1324969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * 1334969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * 3. Concatenate copies of the password together to create a string P of 1344969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * length v(ceiling(p/v)) bits (the final copy of the password may be 1354969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * truncated to create P). Note that if the password is the empty string, 1364969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * then so is P. 1374969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * 1384969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * 4. Set I=S||P to be the concatenation of S and P. */ 1394969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (salt_len + block_size - 1 < salt_len || 1404969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin pass_raw_len + block_size - 1 < pass_raw_len) { 1414969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); 1424969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin return 0; 143e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 1444969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin size_t S_len = block_size * ((salt_len + block_size - 1) / block_size); 1454969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin size_t P_len = block_size * ((pass_raw_len + block_size - 1) / block_size); 1464969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin size_t I_len = S_len + P_len; 1474969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (I_len < S_len) { 1484969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); 1494969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin return 0; 150e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 1514969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1524969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin uint8_t *I = OPENSSL_malloc(I_len); 1534969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (I_len != 0 && I == NULL) { 1544969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); 1554969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin return 0; 156e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 1574969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1587c0d06c221ce9edf44bbf978b909b38a0aee2084David Benjamin for (size_t i = 0; i < S_len; i++) { 1594969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin I[i] = salt[i % salt_len]; 160e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 1617c0d06c221ce9edf44bbf978b909b38a0aee2084David Benjamin for (size_t i = 0; i < P_len; i++) { 1624969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin I[i + S_len] = pass_raw[i % pass_raw_len]; 1634969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin } 1644969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1654969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin int ret = 0; 1664969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin EVP_MD_CTX ctx; 1674969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin EVP_MD_CTX_init(&ctx); 1684969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1694969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin while (out_len != 0) { 1704969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin /* A. Set A_i=H^r(D||I). (i.e., the r-th hash of D||I, 1714969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * H(H(H(... H(D||I)))) */ 1724969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin uint8_t A[EVP_MAX_MD_SIZE]; 1734969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin unsigned A_len; 1744969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (!EVP_DigestInit_ex(&ctx, md, NULL) || 1754969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !EVP_DigestUpdate(&ctx, D, block_size) || 1764969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !EVP_DigestUpdate(&ctx, I, I_len) || 1774969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !EVP_DigestFinal_ex(&ctx, A, &A_len)) { 178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1807c0d06c221ce9edf44bbf978b909b38a0aee2084David Benjamin for (int iter = 1; iter < iterations; iter++) { 1814969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (!EVP_DigestInit_ex(&ctx, md, NULL) || 1824969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !EVP_DigestUpdate(&ctx, A, A_len) || 1834969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !EVP_DigestFinal_ex(&ctx, A, &A_len)) { 184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1874969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1884969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin size_t todo = out_len < A_len ? out_len : A_len; 18969939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan OPENSSL_memcpy(out, A, todo); 1904969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin out += todo; 1914969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin out_len -= todo; 1924969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (out_len == 0) { 1934969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin break; 194e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 1954969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1964969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin /* B. Concatenate copies of A_i to create a string B of length v bits (the 1974969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * final copy of A_i may be truncated to create B). */ 1984969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin uint8_t B[EVP_MAX_MD_BLOCK_SIZE]; 1997c0d06c221ce9edf44bbf978b909b38a0aee2084David Benjamin for (size_t i = 0; i < block_size; i++) { 2004969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin B[i] = A[i % A_len]; 201e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 2024969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 2034969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin /* C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit blocks, 2044969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * where k=ceiling(s/v)+ceiling(p/v), modify I by setting I_j=(I_j+B+1) mod 2054969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * 2^v for each j. */ 2064969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin assert(I_len % block_size == 0); 2077c0d06c221ce9edf44bbf978b909b38a0aee2084David Benjamin for (size_t i = 0; i < I_len; i += block_size) { 2084969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin unsigned carry = 1; 2097c0d06c221ce9edf44bbf978b909b38a0aee2084David Benjamin for (size_t j = block_size - 1; j < block_size; j--) { 2104969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin carry += I[i + j] + B[j]; 2114969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin I[i + j] = (uint8_t)carry; 2124969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin carry >>= 8; 213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 2174969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin ret = 1; 218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 2194969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjaminerr: 2204969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_cleanse(I, I_len); 221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(I); 222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_MD_CTX_cleanup(&ctx); 223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 226d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int pkcs12_pbe_keyivgen(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw, 227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t pass_raw_len, ASN1_TYPE *param, 228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EVP_CIPHER *cipher, const EVP_MD *md, 229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int is_encrypt) { 230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley PBEPARAM *pbe; 231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int salt_len, iterations, ret; 232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *salt; 233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *pbuf; 234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; 235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Extract useful info from parameter */ 237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (param == NULL || param->type != V_ASN1_SEQUENCE || 238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley param->value.sequence == NULL) { 239b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); 240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pbuf = param->value.sequence->data; 244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length); 245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (pbe == NULL) { 246b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); 247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pbe->iter) { 251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley iterations = 1; 252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley iterations = ASN1_INTEGER_get(pbe->iter); 254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley salt = pbe->salt->data; 256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley salt_len = pbe->salt->length; 257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pkcs12_key_gen_raw(pass_raw, pass_raw_len, salt, salt_len, PKCS12_KEY_ID, 258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley iterations, EVP_CIPHER_key_length(cipher), key, md)) { 259b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEY_GEN_ERROR); 260d9e397b599b13d642138480a28c14db7a136bf0Adam Langley PBEPARAM_free(pbe); 261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pkcs12_key_gen_raw(pass_raw, pass_raw_len, salt, salt_len, PKCS12_IV_ID, 264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley iterations, EVP_CIPHER_iv_length(cipher), iv, md)) { 265b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEY_GEN_ERROR); 266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley PBEPARAM_free(pbe); 267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley PBEPARAM_free(pbe); 270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, is_encrypt); 271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH); 272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH); 273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 276d9e397b599b13d642138480a28c14db7a136bf0Adam Langleytypedef int (*keygen_func)(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw, 277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t pass_raw_len, ASN1_TYPE *param, 278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EVP_CIPHER *cipher, const EVP_MD *md, 279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int is_encrypt); 280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystruct pbe_suite { 282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int pbe_nid; 283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EVP_CIPHER* (*cipher_func)(void); 284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EVP_MD* (*md_func)(void); 285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley keygen_func keygen; 286b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root int flags; 287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 289b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#define PBE_UCS2_CONVERT_PASSWORD 0x1 290b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 291d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const struct pbe_suite kBuiltinPBE[] = { 292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 293b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc, EVP_sha1, 294b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root pkcs12_pbe_keyivgen, PBE_UCS2_CONVERT_PASSWORD 295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley }, 296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley NID_pbe_WithSHA1And128BitRC4, EVP_rc4, EVP_sha1, pkcs12_pbe_keyivgen, 298b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root PBE_UCS2_CONVERT_PASSWORD 299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley }, 300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley NID_pbe_WithSHA1And3_Key_TripleDES_CBC, EVP_des_ede3_cbc, EVP_sha1, 302b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root pkcs12_pbe_keyivgen, PBE_UCS2_CONVERT_PASSWORD 303b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root }, 304b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root { 305b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root NID_pbes2, NULL, NULL, PKCS5_v2_PBE_keyivgen, 0 306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley }, 307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 309b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootstatic const struct pbe_suite *get_pbe_suite(int pbe_nid) { 310b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root unsigned i; 311f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin for (i = 0; i < OPENSSL_ARRAY_SIZE(kBuiltinPBE); i++) { 312b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (kBuiltinPBE[i].pbe_nid == pbe_nid) { 313b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return &kBuiltinPBE[i]; 314b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 315b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 316b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 317b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return NULL; 318b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root} 319b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 320b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root/* pass_to_pass_raw performs a password conversion (possibly a no-op) 321b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * appropriate to the supplied |pbe_nid|. The input |pass| is treated as a 322b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * NUL-terminated string if |pass_len| is -1, otherwise it is treated as a 323b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * buffer of the specified length. If the supplied PBE NID sets the 324b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * |PBE_UCS2_CONVERT_PASSWORD| flag, the supplied |pass| will be converted to 325b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * UCS-2. 326b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * 327b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * It sets |*out_pass_raw| to a new buffer that must be freed by the caller. It 328b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * returns one on success and zero on error. */ 329b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootstatic int pass_to_pass_raw(int pbe_nid, const char *pass, int pass_len, 330b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root uint8_t **out_pass_raw, size_t *out_pass_raw_len) { 331b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (pass == NULL) { 332b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root *out_pass_raw = NULL; 333b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root *out_pass_raw_len = 0; 334b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 1; 335b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 336b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 337b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (pass_len == -1) { 338b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root pass_len = strlen(pass); 339b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } else if (pass_len < 0 || pass_len > 2000000000) { 340b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); 341b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 0; 342b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 343b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 344b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root const struct pbe_suite *suite = get_pbe_suite(pbe_nid); 345b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (suite != NULL && (suite->flags & PBE_UCS2_CONVERT_PASSWORD)) { 346b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (!ascii_to_ucs2(pass, pass_len, out_pass_raw, out_pass_raw_len)) { 347b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); 348b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 0; 349b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 350b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } else { 351b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root *out_pass_raw = BUF_memdup(pass, pass_len); 352b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (*out_pass_raw == NULL) { 353b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); 354b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 0; 355b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 356b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root *out_pass_raw_len = (size_t)pass_len; 357b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 358b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 359b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 1; 360b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root} 361b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 362d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int pbe_cipher_init(ASN1_OBJECT *pbe_obj, 363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *pass_raw, size_t pass_raw_len, 364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ASN1_TYPE *param, 365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_CIPHER_CTX *ctx, int is_encrypt) { 366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EVP_CIPHER *cipher; 367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EVP_MD *md; 368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 369b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root const struct pbe_suite *suite = get_pbe_suite(OBJ_obj2nid(pbe_obj)); 370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (suite == NULL) { 371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley char obj_str[80]; 372b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_ALGORITHM); 373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pbe_obj) { 374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley strncpy(obj_str, "NULL", sizeof(obj_str)); 375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley i2t_ASN1_OBJECT(obj_str, sizeof(obj_str), pbe_obj); 377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ERR_add_error_data(2, "TYPE=", obj_str); 379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (suite->cipher_func == NULL) { 383d9e397b599b13d642138480a28c14db7a136bf0Adam Langley cipher = NULL; 384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley cipher = suite->cipher_func(); 386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!cipher) { 387b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_CIPHER); 388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (suite->md_func == NULL) { 393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley md = NULL; 394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 395d9e397b599b13d642138480a28c14db7a136bf0Adam Langley md = suite->md_func(); 396d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!md) { 397b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_DIGEST); 398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 402d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!suite->keygen(ctx, pass_raw, pass_raw_len, param, cipher, md, 403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley is_encrypt)) { 404b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEYGEN_FAILURE); 405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 408d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 411d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int pbe_crypt(const X509_ALGOR *algor, 412d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *pass_raw, size_t pass_raw_len, 413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *in, size_t in_len, 414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t **out, size_t *out_len, 415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int is_encrypt) { 416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *buf; 417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int n, ret = 0; 418d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_CIPHER_CTX ctx; 419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unsigned block_size; 420d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_CIPHER_CTX_init(&ctx); 422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pbe_cipher_init(algor->algorithm, pass_raw, pass_raw_len, 424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley algor->parameter, &ctx, is_encrypt)) { 425b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_CIPHER_ALGORITHM); 426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley block_size = EVP_CIPHER_CTX_block_size(&ctx); 429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (in_len + block_size < in_len) { 431b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_TOO_LONG); 432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley buf = OPENSSL_malloc(in_len + block_size); 436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (buf == NULL) { 437b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); 438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 439d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 440d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EVP_CipherUpdate(&ctx, buf, &n, in, in_len)) { 442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(buf); 443b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, ERR_R_EVP_LIB); 444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *out_len = n; 447d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 448d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EVP_CipherFinal_ex(&ctx, buf + n, &n)) { 449d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(buf); 450b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, ERR_R_EVP_LIB); 451d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 452d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 453d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *out_len += n; 454d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *out = buf; 455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 457d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 458d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_CIPHER_CTX_cleanup(&ctx); 459d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 460d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 461d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 462d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic void *pkcs12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it, 463d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *pass_raw, 464d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t pass_raw_len, 465d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ASN1_OCTET_STRING *oct) { 466d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *out; 467d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *p; 468d9e397b599b13d642138480a28c14db7a136bf0Adam Langley void *ret; 469d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t out_len; 470d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 471d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pbe_crypt(algor, pass_raw, pass_raw_len, oct->data, oct->length, 472d9e397b599b13d642138480a28c14db7a136bf0Adam Langley &out, &out_len, 0 /* decrypt */)) { 473b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_CRYPT_ERROR); 474d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 475d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 476d9e397b599b13d642138480a28c14db7a136bf0Adam Langley p = out; 477d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = ASN1_item_d2i(NULL, &p, out_len, it); 478d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_cleanse(out, out_len); 479d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ret) { 480b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); 481d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 482d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(out); 483d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 484d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 485d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 486d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyPKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, const char *pass, 487d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int pass_len) { 488d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *pass_raw = NULL; 489d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t pass_raw_len = 0; 490b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (!pass_to_pass_raw(OBJ_obj2nid(pkcs8->algor->algorithm), pass, pass_len, 491b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root &pass_raw, &pass_raw_len)) { 492b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return NULL; 493d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 494d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 495b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root PKCS8_PRIV_KEY_INFO *ret = PKCS8_decrypt_pbe(pkcs8, pass_raw, pass_raw_len); 496d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 497d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (pass_raw) { 498d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_cleanse(pass_raw, pass_raw_len); 499d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(pass_raw); 500d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 501d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 502d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 503d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 504d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyPKCS8_PRIV_KEY_INFO *PKCS8_decrypt_pbe(X509_SIG *pkcs8, const uint8_t *pass_raw, 505d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t pass_raw_len) { 506d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return pkcs12_item_decrypt_d2i(pkcs8->algor, 507d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass_raw, 508d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pass_raw_len, pkcs8->digest); 509d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 510d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 511d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic ASN1_OCTET_STRING *pkcs12_item_i2d_encrypt(X509_ALGOR *algor, 512d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const ASN1_ITEM *it, 513d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *pass_raw, 514d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t pass_raw_len, void *obj) { 515d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ASN1_OCTET_STRING *oct; 516d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *in = NULL; 517d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int in_len; 518d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t crypt_len; 519d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 520d9e397b599b13d642138480a28c14db7a136bf0Adam Langley oct = M_ASN1_OCTET_STRING_new(); 521d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (oct == NULL) { 522b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); 523d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 524d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 525d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in_len = ASN1_item_i2d(obj, &in, it); 526d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!in) { 527b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCODE_ERROR); 528d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 529d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 530d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pbe_crypt(algor, pass_raw, pass_raw_len, in, in_len, &oct->data, &crypt_len, 531d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1 /* encrypt */)) { 532b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCRYPT_ERROR); 533d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(in); 534d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 535d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 536d9e397b599b13d642138480a28c14db7a136bf0Adam Langley oct->length = crypt_len; 537d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_cleanse(in, in_len); 538d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(in); 539d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return oct; 540d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 541d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 542d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyX509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass, 543d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int pass_len, uint8_t *salt, size_t salt_len, 544d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int iterations, PKCS8_PRIV_KEY_INFO *p8inf) { 545d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *pass_raw = NULL; 546d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t pass_raw_len = 0; 547b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (!pass_to_pass_raw(pbe_nid, pass, pass_len, &pass_raw, &pass_raw_len)) { 548b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return NULL; 549d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 550d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 551b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root X509_SIG *ret = PKCS8_encrypt_pbe(pbe_nid, cipher, pass_raw, pass_raw_len, 552b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root salt, salt_len, iterations, p8inf); 553d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 554d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (pass_raw) { 555d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_cleanse(pass_raw, pass_raw_len); 556d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(pass_raw); 557d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 558d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 559d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 560d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 561b8494591d1b1a143f3b192d845c238bbf3bc629dKenny RootX509_SIG *PKCS8_encrypt_pbe(int pbe_nid, const EVP_CIPHER *cipher, 562d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *pass_raw, size_t pass_raw_len, 563d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *salt, size_t salt_len, 564d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int iterations, PKCS8_PRIV_KEY_INFO *p8inf) { 565d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_SIG *pkcs8 = NULL; 566d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_ALGOR *pbe; 567d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 568d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pkcs8 = X509_SIG_new(); 569d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (pkcs8 == NULL) { 570b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); 571d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 572d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 573d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 574b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (pbe_nid == -1) { 575b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root pbe = PKCS5_pbe2_set(cipher, iterations, salt, salt_len); 576b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } else { 577b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root pbe = PKCS5_pbe_set(pbe_nid, iterations, salt, salt_len); 578b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 579d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pbe) { 580b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, ERR_R_ASN1_LIB); 581d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 582d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 583d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 584d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_ALGOR_free(pkcs8->algor); 585d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pkcs8->algor = pbe; 586d9e397b599b13d642138480a28c14db7a136bf0Adam Langley M_ASN1_OCTET_STRING_free(pkcs8->digest); 587d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pkcs8->digest = pkcs12_item_i2d_encrypt( 588d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass_raw, pass_raw_len, p8inf); 589d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pkcs8->digest) { 590b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCRYPT_ERROR); 591d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 592d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 593d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 594d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return pkcs8; 595d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 596d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 597d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_SIG_free(pkcs8); 598d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 599d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 600d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 601d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyEVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) { 6024969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin uint8_t *der = NULL; 6034969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin int der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &der); 6044969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (der_len < 0) { 605d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 606e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 607d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 6084969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin CBS cbs; 6094969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin CBS_init(&cbs, der, (size_t)der_len); 6104969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin EVP_PKEY *ret = EVP_parse_private_key(&cbs); 6114969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (ret == NULL || CBS_len(&cbs) != 0) { 6124969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); 6134969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin EVP_PKEY_free(ret); 6144969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_free(der); 615d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 616d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 617d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 6184969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_free(der); 6194969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin return ret; 620d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 621d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 622d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyPKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) { 6234969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin CBB cbb; 6244969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin uint8_t *der = NULL; 6254969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin size_t der_len; 6264969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (!CBB_init(&cbb, 0) || 6274969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !EVP_marshal_private_key(&cbb, pkey) || 6284969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !CBB_finish(&cbb, &der, &der_len) || 6294969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin der_len > LONG_MAX) { 6304969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin CBB_cleanup(&cbb); 6314969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCODE_ERROR); 6324969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin goto err; 633d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 634d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 6354969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin const uint8_t *p = der; 6364969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, (long)der_len); 6374969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (p8 == NULL || p != der + der_len) { 6384969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin PKCS8_PRIV_KEY_INFO_free(p8); 6394969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); 6404969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin goto err; 641d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 6424969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 6434969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_free(der); 644d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return p8; 645d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 6464969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjaminerr: 6474969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_free(der); 648d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 649d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 650d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 651d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystruct pkcs12_context { 652d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY **out_key; 653d9e397b599b13d642138480a28c14db7a136bf0Adam Langley STACK_OF(X509) *out_certs; 654d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *password; 655d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t password_len; 656d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 657d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 658d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int PKCS12_handle_content_info(CBS *content_info, unsigned depth, 659d9e397b599b13d642138480a28c14db7a136bf0Adam Langley struct pkcs12_context *ctx); 660d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 661d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* PKCS12_handle_content_infos parses a series of PKCS#7 ContentInfos in a 662d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SEQUENCE. */ 663d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int PKCS12_handle_content_infos(CBS *content_infos, 664d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unsigned depth, 665d9e397b599b13d642138480a28c14db7a136bf0Adam Langley struct pkcs12_context *ctx) { 666d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *der_bytes = NULL; 667d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t der_len; 668d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS in; 669d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 670d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 671d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Generally we only expect depths 0 (the top level, with a 672d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * pkcs7-encryptedData and a pkcs7-data) and depth 1 (the various PKCS#12 673d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * bags). */ 674d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (depth > 3) { 675b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PKCS12_TOO_DEEPLY_NESTED); 676d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 677d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 678d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 679d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Although a BER->DER conversion is done at the beginning of |PKCS12_parse|, 680d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the ASN.1 data gets wrapped in OCTETSTRINGs and/or encrypted and the 681d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * conversion cannot see through those wrappings. So each time we step 682d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * through one we need to convert to DER again. */ 683d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_asn1_ber_to_der(content_infos, &der_bytes, &der_len)) { 684b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 685d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 686d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 687d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 688d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (der_bytes != NULL) { 689d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_init(&in, der_bytes, der_len); 690d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 691d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_init(&in, CBS_data(content_infos), CBS_len(content_infos)); 692d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 693d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 694d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&in, &in, CBS_ASN1_SEQUENCE)) { 695b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 696d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 697d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 698d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 699d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (CBS_len(&in) > 0) { 700d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS content_info; 701d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE)) { 702b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 703d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 704d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 705d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 706d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!PKCS12_handle_content_info(&content_info, depth + 1, ctx)) { 707d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 708d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 709d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 710d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 711d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* NSS includes additional data after the SEQUENCE, but it's an (unwrapped) 712d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copy of the same encrypted private key (with the same IV and 713d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ciphertext)! */ 714d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 715d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 716d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 717d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 718e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley OPENSSL_free(der_bytes); 719d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 720d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 721d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 722d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a 723d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PKCS#12 structure. */ 724d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int PKCS12_handle_content_info(CBS *content_info, unsigned depth, 725d9e397b599b13d642138480a28c14db7a136bf0Adam Langley struct pkcs12_context *ctx) { 726d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS content_type, wrapped_contents, contents, content_infos; 727d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int nid, ret = 0; 7284969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin uint8_t *storage = NULL; 729d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 730d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) || 731d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(content_info, &wrapped_contents, 732d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { 733b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 734d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 735d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 736d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 737d9e397b599b13d642138480a28c14db7a136bf0Adam Langley nid = OBJ_cbs2nid(&content_type); 738d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (nid == NID_pkcs7_encrypted) { 739d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* See https://tools.ietf.org/html/rfc2315#section-13. 740d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 741d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PKCS#7 encrypted data inside a PKCS#12 structure is generally an 742d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * encrypted certificate bag and it's generally encrypted with 40-bit 743d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * RC2-CBC. */ 744d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS version_bytes, eci, contents_type, ai, encrypted_contents; 745d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_ALGOR *algor = NULL; 746d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *inp; 747d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *out; 748d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t out_len; 749d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 750d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) || 751d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) || 752d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* EncryptedContentInfo, see 753d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * https://tools.ietf.org/html/rfc2315#section-10.1 */ 754d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) || 755d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) || 756d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* AlgorithmIdentifier, see 757d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */ 758d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1_element(&eci, &ai, CBS_ASN1_SEQUENCE) || 7594969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !CBS_get_asn1_implicit_string( 7604969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin &eci, &encrypted_contents, &storage, 7614969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin CBS_ASN1_CONTEXT_SPECIFIC | 0, CBS_ASN1_OCTETSTRING)) { 762b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 763d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 764d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 765d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 7664139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (OBJ_cbs2nid(&contents_type) != NID_pkcs7_data || 7674139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley CBS_len(&ai) > LONG_MAX) { 768b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 769d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 770d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 771d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 772d9e397b599b13d642138480a28c14db7a136bf0Adam Langley inp = CBS_data(&ai); 7734139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley algor = d2i_X509_ALGOR(NULL, &inp, (long)CBS_len(&ai)); 774d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (algor == NULL) { 775d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 776d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 777d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (inp != CBS_data(&ai) + CBS_len(&ai)) { 778d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_ALGOR_free(algor); 779b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 780d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 781d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 782d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 783d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pbe_crypt(algor, ctx->password, ctx->password_len, 784d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_data(&encrypted_contents), CBS_len(&encrypted_contents), 785d9e397b599b13d642138480a28c14db7a136bf0Adam Langley &out, &out_len, 0 /* decrypt */)) { 786d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_ALGOR_free(algor); 787d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 788d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 789d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_ALGOR_free(algor); 790d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 791d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_init(&content_infos, out, out_len); 792d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = PKCS12_handle_content_infos(&content_infos, depth + 1, ctx); 793d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(out); 794d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else if (nid == NID_pkcs7_data) { 795d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS octet_string_contents; 796d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 797d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents, 798d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_ASN1_OCTETSTRING)) { 799b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 800d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 801d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 802d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 803d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = PKCS12_handle_content_infos(&octet_string_contents, depth + 1, ctx); 804d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else if (nid == NID_pkcs8ShroudedKeyBag) { 805d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section 806d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4.2.2. */ 807d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *inp = CBS_data(&wrapped_contents); 808d9e397b599b13d642138480a28c14db7a136bf0Adam Langley PKCS8_PRIV_KEY_INFO *pki = NULL; 809d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_SIG *encrypted = NULL; 810d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 811d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (*ctx->out_key) { 812b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12); 813d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 814d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 815d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 8164139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (CBS_len(&wrapped_contents) > LONG_MAX) { 8174139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 8184139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley goto err; 8194139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley } 8204139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley 821d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* encrypted isn't actually an X.509 signature, but it has the same 822d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * structure as one and so |X509_SIG| is reused to store it. */ 8234139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley encrypted = d2i_X509_SIG(NULL, &inp, (long)CBS_len(&wrapped_contents)); 824d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (encrypted == NULL) { 825b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 826d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 827d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 828d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (inp != CBS_data(&wrapped_contents) + CBS_len(&wrapped_contents)) { 829b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 830d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_SIG_free(encrypted); 831d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 832d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 833d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 834d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pki = PKCS8_decrypt_pbe(encrypted, ctx->password, ctx->password_len); 835d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_SIG_free(encrypted); 836d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (pki == NULL) { 837d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 838d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 839d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 840d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *ctx->out_key = EVP_PKCS82PKEY(pki); 841d9e397b599b13d642138480a28c14db7a136bf0Adam Langley PKCS8_PRIV_KEY_INFO_free(pki); 842d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 843d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ctx->out_key == NULL) { 844d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 845d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 846d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 847d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else if (nid == NID_certBag) { 848d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS cert_bag, cert_type, wrapped_cert, cert; 849d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 850d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&wrapped_contents, &cert_bag, CBS_ASN1_SEQUENCE) || 851d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) || 852d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&cert_bag, &wrapped_cert, 853d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || 854d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) { 855b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 856d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 857d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 858d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 859d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (OBJ_cbs2nid(&cert_type) == NID_x509Certificate) { 8604139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (CBS_len(&cert) > LONG_MAX) { 8614139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 8624139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley goto err; 8634139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley } 864d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *inp = CBS_data(&cert); 8654139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley X509 *x509 = d2i_X509(NULL, &inp, (long)CBS_len(&cert)); 866d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!x509) { 867b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 868d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 869d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 870d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (inp != CBS_data(&cert) + CBS_len(&cert)) { 871b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 872d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_free(x509); 873d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 874d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 875d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 876d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (0 == sk_X509_push(ctx->out_certs, x509)) { 877d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_free(x509); 878d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 879d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 880d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 881d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 882d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 883d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Unknown element type - ignore it. */ 884d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 885d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 886d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 887d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 8884969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_free(storage); 889d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 890d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 891d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 892d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs, 893d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS *ber_in, const char *password) { 894d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *der_bytes = NULL; 895d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t der_len; 896d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS in, pfx, mac_data, authsafe, content_type, wrapped_authsafes, authsafes; 897d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint64_t version; 898d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 899d9e397b599b13d642138480a28c14db7a136bf0Adam Langley struct pkcs12_context ctx; 900d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const size_t original_out_certs_len = sk_X509_num(out_certs); 901d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 902d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* The input may be in BER format. */ 903d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_asn1_ber_to_der(ber_in, &der_bytes, &der_len)) { 904b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 905d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 906d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 907d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (der_bytes != NULL) { 908d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_init(&in, der_bytes, der_len); 909d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 910d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_init(&in, CBS_data(ber_in), CBS_len(ber_in)); 911d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 912d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 913d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *out_key = NULL; 91469939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan OPENSSL_memset(&ctx, 0, sizeof(ctx)); 915d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 916d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section 917d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * four. */ 918d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&in, &pfx, CBS_ASN1_SEQUENCE) || 919d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_len(&in) != 0 || 920d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1_uint64(&pfx, &version)) { 921b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 922d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 923d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 924d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 925d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (version < 3) { 926b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_VERSION); 927d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 928d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 929d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 930d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&pfx, &authsafe, CBS_ASN1_SEQUENCE)) { 931b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 932d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 933d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 934d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 935d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (CBS_len(&pfx) == 0) { 936b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MISSING_MAC); 937d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 938d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 939d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 940d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE)) { 941b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 942d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 943d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 944d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 945d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* authsafe is a PKCS#7 ContentInfo. See 946d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * https://tools.ietf.org/html/rfc2315#section-7. */ 947d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&authsafe, &content_type, CBS_ASN1_OBJECT) || 948d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&authsafe, &wrapped_authsafes, 949d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { 950b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 951d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 952d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 953d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 954d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* The content type can either be |NID_pkcs7_data| or |NID_pkcs7_signed|. The 955d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * latter indicates that it's signed by a public key, which isn't 956d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * supported. */ 957d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (OBJ_cbs2nid(&content_type) != NID_pkcs7_data) { 958b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED); 959d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 960d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 961d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 962d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&wrapped_authsafes, &authsafes, CBS_ASN1_OCTETSTRING)) { 963b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 964d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 965d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 966d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 967d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ctx.out_key = out_key; 968d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ctx.out_certs = out_certs; 9694969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (!ascii_to_ucs2(password, password ? strlen(password) : 0, &ctx.password, 970d9e397b599b13d642138480a28c14db7a136bf0Adam Langley &ctx.password_len)) { 971b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); 972d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 973d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 974d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 975d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Verify the MAC. */ 976d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 977d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS mac, hash_type_seq, hash_oid, salt, expected_mac; 978d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint64_t iterations; 979d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int hash_nid; 980d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EVP_MD *md; 981d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t hmac_key[EVP_MAX_MD_SIZE]; 982d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t hmac[EVP_MAX_MD_SIZE]; 983d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unsigned hmac_len; 984d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 985d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&mac_data, &mac, CBS_ASN1_SEQUENCE) || 986d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&mac, &hash_type_seq, CBS_ASN1_SEQUENCE) || 987d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&hash_type_seq, &hash_oid, CBS_ASN1_OBJECT) || 988d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&mac, &expected_mac, CBS_ASN1_OCTETSTRING) || 989d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&mac_data, &salt, CBS_ASN1_OCTETSTRING)) { 990b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 991d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 992d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 993d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 994d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* The iteration count is optional and the default is one. */ 995d9e397b599b13d642138480a28c14db7a136bf0Adam Langley iterations = 1; 996d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (CBS_len(&mac_data) > 0) { 997d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1_uint64(&mac_data, &iterations) || 998d9e397b599b13d642138480a28c14db7a136bf0Adam Langley iterations > INT_MAX) { 999b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); 1000d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 1001d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1002d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1003d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1004d9e397b599b13d642138480a28c14db7a136bf0Adam Langley hash_nid = OBJ_cbs2nid(&hash_oid); 1005d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (hash_nid == NID_undef || 1006d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (md = EVP_get_digestbynid(hash_nid)) == NULL) { 1007b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_HASH); 1008d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 1009d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1010d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1011d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pkcs12_key_gen_raw(ctx.password, ctx.password_len, CBS_data(&salt), 1012d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_len(&salt), PKCS12_MAC_ID, iterations, 1013d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_MD_size(md), hmac_key, md)) { 1014d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 1015d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1016d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1017d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (NULL == HMAC(md, hmac_key, EVP_MD_size(md), CBS_data(&authsafes), 1018d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_len(&authsafes), hmac, &hmac_len)) { 1019d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 1020d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1021d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1022d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_mem_equal(&expected_mac, hmac, hmac_len)) { 1023b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_INCORRECT_PASSWORD); 1024d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 1025d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1026d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1027d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1028d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* authsafes contains a series of PKCS#7 ContentInfos. */ 1029d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!PKCS12_handle_content_infos(&authsafes, 0, &ctx)) { 1030d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 1031d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1032d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1033d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 1034d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1035d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 1036e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley OPENSSL_free(ctx.password); 1037e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley OPENSSL_free(der_bytes); 1038d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ret) { 1039e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley EVP_PKEY_free(*out_key); 1040e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *out_key = NULL; 1041d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (sk_X509_num(out_certs) > original_out_certs_len) { 1042d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509 *x509 = sk_X509_pop(out_certs); 1043d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_free(x509); 1044d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1045d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1046d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1047d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 1048d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 1049d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1050d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid PKCS12_PBE_add(void) {} 1051d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1052d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystruct pkcs12_st { 1053d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *ber_bytes; 1054d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t ber_len; 1055d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 1056d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1057d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyPKCS12* d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes, size_t ber_len) { 1058d9e397b599b13d642138480a28c14db7a136bf0Adam Langley PKCS12 *p12; 1059d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1060d9e397b599b13d642138480a28c14db7a136bf0Adam Langley p12 = OPENSSL_malloc(sizeof(PKCS12)); 1061d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!p12) { 1062d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 1063d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1064d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1065d9e397b599b13d642138480a28c14db7a136bf0Adam Langley p12->ber_bytes = OPENSSL_malloc(ber_len); 1066d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!p12->ber_bytes) { 1067d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(p12); 1068d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 1069d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1070d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 107169939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan OPENSSL_memcpy(p12->ber_bytes, *ber_bytes, ber_len); 1072d9e397b599b13d642138480a28c14db7a136bf0Adam Langley p12->ber_len = ber_len; 1073d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *ber_bytes += ber_len; 1074d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 10754969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (out_p12) { 10764969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin PKCS12_free(*out_p12); 10774969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 10784969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin *out_p12 = p12; 10794969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin } 10804969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1081d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return p12; 1082d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 1083d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1084d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyPKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12) { 1085d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t used = 0; 1086d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BUF_MEM *buf; 1087d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *dummy; 1088d9e397b599b13d642138480a28c14db7a136bf0Adam Langley static const size_t kMaxSize = 256 * 1024; 1089d9e397b599b13d642138480a28c14db7a136bf0Adam Langley PKCS12 *ret = NULL; 1090d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1091d9e397b599b13d642138480a28c14db7a136bf0Adam Langley buf = BUF_MEM_new(); 1092d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (buf == NULL) { 1093d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 1094d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1095d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BUF_MEM_grow(buf, 8192) == 0) { 1096d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto out; 1097d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1098d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1099d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (;;) { 1100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int n = BIO_read(bio, &buf->data[used], buf->length - used); 1101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (n < 0) { 11024969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (used == 0) { 11034969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin goto out; 11044969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin } 11054969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin /* Workaround a bug in node.js. It uses a memory BIO for this in the wrong 11064969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * mode. */ 11074969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin n = 0; 1108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (n == 0) { 1111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley break; 1112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley used += n; 1114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (used < buf->length) { 1116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley continue; 1117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (buf->length > kMaxSize || 1120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BUF_MEM_grow(buf, buf->length * 2) == 0) { 1121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto out; 1122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley dummy = (uint8_t*) buf->data; 1126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = d2i_PKCS12(out_p12, &dummy, used); 1127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1128d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyout: 1129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BUF_MEM_free(buf); 1130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 1131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 1132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1133d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyPKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12) { 1134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO *bio; 1135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley PKCS12 *ret; 1136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio = BIO_new_fp(fp, 0 /* don't take ownership */); 1138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!bio) { 1139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 1140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = d2i_PKCS12_bio(bio, out_p12); 1143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_free(bio); 1144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 1145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 1146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1147d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint PKCS12_parse(const PKCS12 *p12, const char *password, EVP_PKEY **out_pkey, 1148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509 **out_cert, STACK_OF(X509) **out_ca_certs) { 1149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS ber_bytes; 1150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley STACK_OF(X509) *ca_certs = NULL; 1151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley char ca_certs_alloced = 0; 1152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (out_ca_certs != NULL && *out_ca_certs != NULL) { 1154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ca_certs = *out_ca_certs; 1155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ca_certs) { 1158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ca_certs = sk_X509_new_null(); 1159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ca_certs == NULL) { 1160b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); 1161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 1162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ca_certs_alloced = 1; 1164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_init(&ber_bytes, p12->ber_bytes, p12->ber_len); 1167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!PKCS12_get_key_and_certs(out_pkey, ca_certs, &ber_bytes, password)) { 1168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ca_certs_alloced) { 1169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley sk_X509_free(ca_certs); 1170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 1172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *out_cert = NULL; 1175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (sk_X509_num(ca_certs) > 0) { 1176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *out_cert = sk_X509_shift(ca_certs); 1177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (out_ca_certs) { 1180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *out_ca_certs = ca_certs; 1181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 1182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley sk_X509_pop_free(ca_certs, X509_free); 1183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 1186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 1187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1188e99801b603dea8893dcc61c70b327ef2d00b652cKenny Rootint PKCS12_verify_mac(const PKCS12 *p12, const char *password, 1189e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root int password_len) { 1190e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root if (password == NULL) { 1191e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root if (password_len != 0) { 1192e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root return 0; 1193e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root } 1194e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root } else if (password_len != -1 && 1195e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root (password[password_len] != 0 || 119669939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan OPENSSL_memchr(password, 0, password_len) != NULL)) { 1197e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root return 0; 1198e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root } 1199e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root 1200e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root EVP_PKEY *pkey = NULL; 1201e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root X509 *cert = NULL; 1202e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root if (!PKCS12_parse(p12, password, &pkey, &cert, NULL)) { 1203e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root ERR_clear_error(); 1204e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root return 0; 1205e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root } 1206e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root 1207e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root EVP_PKEY_free(pkey); 1208e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root X509_free(cert); 1209e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root 1210e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root return 1; 1211e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root} 1212e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root 1213d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid PKCS12_free(PKCS12 *p12) { 12144969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (p12 == NULL) { 12154969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin return; 12164969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin } 1217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(p12->ber_bytes); 1218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(p12); 1219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 1220