1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
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 //     http://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 "ssl_pkey.h"
16 #include "ssl_methods.h"
17 #include "ssl_dbg.h"
18 #include "ssl_port.h"
19 #include "openssl/bio.h"
20 
21 /**
22  * @brief create a private key object according to input private key
23  */
__EVP_PKEY_new(EVP_PKEY * ipk)24 EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk)
25 {
26     int ret;
27     EVP_PKEY *pkey;
28 
29     pkey = ssl_mem_zalloc(sizeof(EVP_PKEY));
30     if (!pkey) {
31         SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "no enough memory > (pkey)");
32         goto no_mem;
33     }
34 
35     pkey->ref_counter = 1;
36 
37     if (ipk) {
38         pkey->method = ipk->method;
39     } else {
40         pkey->method = EVP_PKEY_method();
41     }
42 
43     ret = EVP_PKEY_METHOD_CALL(new, pkey, ipk);
44     if (ret) {
45         SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(new) return %d", ret);
46         goto failed;
47     }
48 
49     return pkey;
50 
51 failed:
52     ssl_mem_free(pkey);
53 no_mem:
54     return NULL;
55 }
56 
57 /**
58  * @brief create a private key object
59  */
EVP_PKEY_new(void)60 EVP_PKEY* EVP_PKEY_new(void)
61 {
62     return __EVP_PKEY_new(NULL);
63 }
64 
65 /**
66  * @brief free a private key object
67  */
EVP_PKEY_free(EVP_PKEY * pkey)68 void EVP_PKEY_free(EVP_PKEY *pkey)
69 {
70     SSL_ASSERT3(pkey);
71 
72     if (--pkey->ref_counter > 0) {
73         return;
74     }
75 
76     EVP_PKEY_METHOD_CALL(free, pkey);
77 
78     ssl_mem_free(pkey);
79 }
80 
81 /**
82  * @brief load a character key context into system context. If '*a' is pointed to the
83  *        private key, then load key into it. Or create a new private key object
84  */
d2i_PrivateKey(int type,EVP_PKEY ** a,const unsigned char ** pp,long length)85 EVP_PKEY *d2i_PrivateKey(int type,
86                          EVP_PKEY **a,
87                          const unsigned char **pp,
88                          long length)
89 {
90     int m = 0;
91     int ret;
92     EVP_PKEY *pkey;
93 
94     SSL_ASSERT2(pp);
95     SSL_ASSERT2(*pp);
96     SSL_ASSERT2(length);
97 
98     if (a && *a) {
99         pkey = *a;
100     } else {
101         pkey = EVP_PKEY_new();;
102         if (!pkey) {
103             SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_new() return NULL");
104             goto failed1;
105         }
106 
107         m = 1;
108     }
109 
110     ret = EVP_PKEY_METHOD_CALL(load, pkey, *pp, length);
111     if (ret) {
112         SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(load) return %d", ret);
113         goto failed2;
114     }
115 
116     if (a)
117         *a = pkey;
118 
119     return pkey;
120 
121 failed2:
122     if (m)
123         EVP_PKEY_free(pkey);
124 failed1:
125     return NULL;
126 }
127 
d2i_PrivateKey_bio(BIO * bp,EVP_PKEY ** a)128 EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
129 {
130     return d2i_PrivateKey(0, a, (const unsigned char **)&bp->data, bp->dlen);
131 }
132 
d2i_RSAPrivateKey_bio(BIO * bp,RSA ** a)133 RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA **a)
134 {
135     return d2i_PrivateKey_bio(bp, (EVP_PKEY**)a);
136 }
137 
PEM_read_bio_RSAPrivateKey(BIO * bp,RSA ** x,pem_password_cb * cb,void * u)138 RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **x, pem_password_cb *cb, void *u)
139 {
140     return PEM_read_bio_PrivateKey(bp, (EVP_PKEY**)x, cb, u);
141 }
142 
PEM_read_bio_PrivateKey(BIO * bp,EVP_PKEY ** pk,pem_password_cb * cb,void * u)143 EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **pk, pem_password_cb *cb, void *u)
144 {
145 
146     int m = 0;
147     int ret;
148     EVP_PKEY *x;
149 
150     SSL_ASSERT2(BIO_method_type(bp) &  BIO_TYPE_MEM);
151     if (bp->data == NULL || bp->dlen == 0) {
152         return NULL;
153     }
154     if (pk && *pk) {
155         x = *pk;
156     } else {
157         x = EVP_PKEY_new();
158         if (!x) {
159             SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_new() return NULL");
160             goto failed;
161         }
162         m = 1;
163     }
164 
165     ret = EVP_PKEY_METHOD_CALL(load, x, bp->data, bp->dlen);
166     if (ret) {
167         SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(load) return %d", ret);
168         goto failed;
169     }
170 
171     // If buffer successfully created a EVP_PKEY from the bio, mark the buffer as consumed
172     bp->data = NULL;
173     bp->dlen = 0;
174     return x;
175 
176     failed:
177     if (m) {
178         EVP_PKEY_free(x);
179     }
180 
181     return NULL;}
182 /**
183  * @brief set the SSL context private key
184  */
SSL_CTX_use_PrivateKey(SSL_CTX * ctx,EVP_PKEY * pkey)185 int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey)
186 {
187     SSL_ASSERT1(ctx);
188     SSL_ASSERT1(pkey);
189 
190     if (ctx->cert->pkey == pkey)
191         return 1;
192 
193     if (ctx->cert->pkey)
194         EVP_PKEY_free(ctx->cert->pkey);
195 
196     pkey->ref_counter++;
197     ctx->cert->pkey = pkey;
198 
199     return 1;
200 }
201 
202 /**
203  * @brief set the SSL private key
204  */
SSL_use_PrivateKey(SSL * ssl,EVP_PKEY * pkey)205 int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
206 {
207     SSL_ASSERT1(ssl);
208     SSL_ASSERT1(pkey);
209 
210     if (ssl->cert->pkey == pkey)
211         return 1;
212 
213     if (ssl->cert->pkey)
214         EVP_PKEY_free(ssl->cert->pkey);
215 
216     ssl->cert->pkey = pkey;
217 
218     return 1;
219 }
220 
221 /**
222  * @brief load private key into the SSL context
223  */
SSL_CTX_use_PrivateKey_ASN1(int type,SSL_CTX * ctx,const unsigned char * d,long len)224 int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx,
225                                 const unsigned char *d, long len)
226 {
227     int ret;
228     EVP_PKEY *pk;
229 
230     pk = d2i_PrivateKey(0, NULL, &d, len);
231     if (!pk) {
232         SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL");
233         goto failed1;
234     }
235 
236     ret = SSL_CTX_use_PrivateKey(ctx, pk);
237     if (!ret) {
238         SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_CTX_use_PrivateKey() return %d", ret);
239         goto failed2;
240     }
241 
242     return 1;
243 
244 failed2:
245     EVP_PKEY_free(pk);
246 failed1:
247     return 0;
248 }
249 
250 /**
251  * @brief load private key into the SSL
252  */
SSL_use_PrivateKey_ASN1(int type,SSL * ssl,const unsigned char * d,long len)253 int SSL_use_PrivateKey_ASN1(int type, SSL *ssl,
254                                 const unsigned char *d, long len)
255 {
256     int ret;
257     EVP_PKEY *pk;
258 
259     pk = d2i_PrivateKey(0, NULL, &d, len);
260     if (!pk) {
261         SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL");
262         goto failed1;
263     }
264 
265     ret = SSL_use_PrivateKey(ssl, pk);
266     if (!ret) {
267         SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_use_PrivateKey() return %d", ret);
268         goto failed2;
269     }
270 
271     return 1;
272 
273 failed2:
274     EVP_PKEY_free(pk);
275 failed1:
276     return 0;
277 }
278 
279 #define ESP_OPENSSL_FILES_IS_SUPPORTED 0
280 /**
281  * @brief load the private key file into SSL context
282  */
SSL_CTX_use_PrivateKey_file(SSL_CTX * ctx,const char * file,int type)283 int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
284 {
285     // Using file name as private key is discouraged
286     SSL_ASSERT1(ESP_OPENSSL_FILES_IS_SUPPORTED);
287     return -1;
288 }
289 
290 /**
291  * @brief load the private key file into SSL
292  */
SSL_use_PrivateKey_file(SSL_CTX * ctx,const char * file,int type)293 int SSL_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
294 {
295     // Using file name as private key is discouraged
296     SSL_ASSERT1(ESP_OPENSSL_FILES_IS_SUPPORTED);
297     return -1;
298 }
299 
300 /**
301  * @brief load the RSA ASN1 private key into SSL context
302  */
SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX * ctx,const unsigned char * d,long len)303 int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len)
304 {
305     return SSL_CTX_use_PrivateKey_ASN1(0, ctx, d, len);
306 }
307 
RSA_free(RSA * r)308 void RSA_free (RSA *r)
309 {
310     EVP_PKEY_free(r);
311 }
312