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