/src/boringssl/crypto/pem/pem_pkey.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <openssl/pem.h> |
16 | | |
17 | | #include <stdio.h> |
18 | | #include <string.h> |
19 | | |
20 | | #include <openssl/dh.h> |
21 | | #include <openssl/err.h> |
22 | | #include <openssl/evp.h> |
23 | | #include <openssl/mem.h> |
24 | | #include <openssl/obj.h> |
25 | | #include <openssl/pkcs8.h> |
26 | | #include <openssl/rand.h> |
27 | | #include <openssl/x509.h> |
28 | | |
29 | | EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, |
30 | 0 | void *u) { |
31 | 0 | char *nm = NULL; |
32 | 0 | const unsigned char *p = NULL; |
33 | 0 | unsigned char *data = NULL; |
34 | 0 | long len; |
35 | 0 | EVP_PKEY *ret = NULL; |
36 | |
|
37 | 0 | if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) { |
38 | 0 | return NULL; |
39 | 0 | } |
40 | 0 | p = data; |
41 | |
|
42 | 0 | if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) { |
43 | 0 | PKCS8_PRIV_KEY_INFO *p8inf; |
44 | 0 | p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); |
45 | 0 | if (!p8inf) { |
46 | 0 | goto p8err; |
47 | 0 | } |
48 | 0 | ret = EVP_PKCS82PKEY(p8inf); |
49 | 0 | if (x) { |
50 | 0 | if (*x) { |
51 | 0 | EVP_PKEY_free((EVP_PKEY *)*x); |
52 | 0 | } |
53 | 0 | *x = ret; |
54 | 0 | } |
55 | 0 | PKCS8_PRIV_KEY_INFO_free(p8inf); |
56 | 0 | } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) { |
57 | 0 | PKCS8_PRIV_KEY_INFO *p8inf; |
58 | 0 | X509_SIG *p8; |
59 | 0 | int pass_len; |
60 | 0 | char psbuf[PEM_BUFSIZE]; |
61 | 0 | p8 = d2i_X509_SIG(NULL, &p, len); |
62 | 0 | if (!p8) { |
63 | 0 | goto p8err; |
64 | 0 | } |
65 | | |
66 | 0 | pass_len = 0; |
67 | 0 | if (!cb) { |
68 | 0 | cb = PEM_def_callback; |
69 | 0 | } |
70 | 0 | pass_len = cb(psbuf, PEM_BUFSIZE, 0, u); |
71 | 0 | if (pass_len < 0) { |
72 | 0 | OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); |
73 | 0 | X509_SIG_free(p8); |
74 | 0 | goto err; |
75 | 0 | } |
76 | 0 | p8inf = PKCS8_decrypt(p8, psbuf, pass_len); |
77 | 0 | X509_SIG_free(p8); |
78 | 0 | OPENSSL_cleanse(psbuf, pass_len); |
79 | 0 | if (!p8inf) { |
80 | 0 | goto p8err; |
81 | 0 | } |
82 | 0 | ret = EVP_PKCS82PKEY(p8inf); |
83 | 0 | if (x) { |
84 | 0 | if (*x) { |
85 | 0 | EVP_PKEY_free((EVP_PKEY *)*x); |
86 | 0 | } |
87 | 0 | *x = ret; |
88 | 0 | } |
89 | 0 | PKCS8_PRIV_KEY_INFO_free(p8inf); |
90 | 0 | } else if (strcmp(nm, PEM_STRING_RSA) == 0) { |
91 | | // TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the |
92 | | // standalone format. This and the cases below probably should not |
93 | | // accept PKCS#8. |
94 | 0 | ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len); |
95 | 0 | } else if (strcmp(nm, PEM_STRING_EC) == 0) { |
96 | 0 | ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len); |
97 | 0 | } else if (strcmp(nm, PEM_STRING_DSA) == 0) { |
98 | 0 | ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len); |
99 | 0 | } |
100 | 0 | p8err: |
101 | 0 | if (ret == NULL) { |
102 | 0 | OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); |
103 | 0 | } |
104 | |
|
105 | 0 | err: |
106 | 0 | OPENSSL_free(nm); |
107 | 0 | OPENSSL_free(data); |
108 | 0 | return ret; |
109 | 0 | } |
110 | | |
111 | | int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, |
112 | | const unsigned char *pass, int pass_len, |
113 | 0 | pem_password_cb *cb, void *u) { |
114 | 0 | return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, (const char *)pass, pass_len, |
115 | 0 | cb, u); |
116 | 0 | } |
117 | | |
118 | | EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, |
119 | 0 | void *u) { |
120 | 0 | BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); |
121 | 0 | if (b == NULL) { |
122 | 0 | OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); |
123 | 0 | return NULL; |
124 | 0 | } |
125 | 0 | EVP_PKEY *ret = PEM_read_bio_PrivateKey(b, x, cb, u); |
126 | 0 | BIO_free(b); |
127 | 0 | return ret; |
128 | 0 | } |
129 | | |
130 | | int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, |
131 | | const unsigned char *pass, int pass_len, |
132 | 0 | pem_password_cb *cb, void *u) { |
133 | 0 | BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); |
134 | 0 | if (b == NULL) { |
135 | 0 | OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); |
136 | 0 | return 0; |
137 | 0 | } |
138 | 0 | int ret = PEM_write_bio_PrivateKey(b, x, enc, pass, pass_len, cb, u); |
139 | 0 | BIO_free(b); |
140 | 0 | return ret; |
141 | 0 | } |