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
20 /**
21 * @brief create a private key object according to input private key
22 */
__EVP_PKEY_new(EVP_PKEY * ipk)23 EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk)
24 {
25 int ret;
26 EVP_PKEY *pkey;
27
28 pkey = ssl_mem_zalloc(sizeof(EVP_PKEY));
29 if (!pkey) {
30 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "no enough memory > (pkey)");
31 goto no_mem;
32 }
33
34 if (ipk) {
35 pkey->method = ipk->method;
36 } else {
37 pkey->method = EVP_PKEY_method();
38 }
39
40 ret = EVP_PKEY_METHOD_CALL(new, pkey, ipk);
41 if (ret) {
42 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(new) return %d", ret);
43 goto failed;
44 }
45
46 return pkey;
47
48 failed:
49 ssl_mem_free(pkey);
50 no_mem:
51 return NULL;
52 }
53
54 /**
55 * @brief create a private key object
56 */
EVP_PKEY_new(void)57 EVP_PKEY* EVP_PKEY_new(void)
58 {
59 return __EVP_PKEY_new(NULL);
60 }
61
62 /**
63 * @brief free a private key object
64 */
EVP_PKEY_free(EVP_PKEY * pkey)65 void EVP_PKEY_free(EVP_PKEY *pkey)
66 {
67 SSL_ASSERT3(pkey);
68
69 EVP_PKEY_METHOD_CALL(free, pkey);
70
71 ssl_mem_free(pkey);
72 }
73
74 /**
75 * @brief load a character key context into system context. If '*a' is pointed to the
76 * private key, then load key into it. Or create a new private key object
77 */
d2i_PrivateKey(int type,EVP_PKEY ** a,const unsigned char ** pp,long length)78 EVP_PKEY *d2i_PrivateKey(int type,
79 EVP_PKEY **a,
80 const unsigned char **pp,
81 long length)
82 {
83 int m = 0;
84 int ret;
85 EVP_PKEY *pkey;
86
87 SSL_ASSERT2(pp);
88 SSL_ASSERT2(*pp);
89 SSL_ASSERT2(length);
90
91 if (a && *a) {
92 pkey = *a;
93 } else {
94 pkey = EVP_PKEY_new();;
95 if (!pkey) {
96 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_new() return NULL");
97 goto failed1;
98 }
99
100 m = 1;
101 }
102
103 ret = EVP_PKEY_METHOD_CALL(load, pkey, *pp, length);
104 if (ret) {
105 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(load) return %d", ret);
106 goto failed2;
107 }
108
109 if (a)
110 *a = pkey;
111
112 return pkey;
113
114 failed2:
115 if (m)
116 EVP_PKEY_free(pkey);
117 failed1:
118 return NULL;
119 }
120
121 /**
122 * @brief set the SSL context private key
123 */
SSL_CTX_use_PrivateKey(SSL_CTX * ctx,EVP_PKEY * pkey)124 int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey)
125 {
126 SSL_ASSERT1(ctx);
127 SSL_ASSERT1(pkey);
128
129 if (ctx->cert->pkey == pkey)
130 return 1;
131
132 if (ctx->cert->pkey)
133 EVP_PKEY_free(ctx->cert->pkey);
134
135 ctx->cert->pkey = pkey;
136
137 return 1;
138 }
139
140 /**
141 * @brief set the SSL private key
142 */
SSL_use_PrivateKey(SSL * ssl,EVP_PKEY * pkey)143 int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
144 {
145 SSL_ASSERT1(ssl);
146 SSL_ASSERT1(pkey);
147
148 if (ssl->cert->pkey == pkey)
149 return 1;
150
151 if (ssl->cert->pkey)
152 EVP_PKEY_free(ssl->cert->pkey);
153
154 ssl->cert->pkey = pkey;
155
156 return 1;
157 }
158
159 /**
160 * @brief load private key into the SSL context
161 */
SSL_CTX_use_PrivateKey_ASN1(int type,SSL_CTX * ctx,const unsigned char * d,long len)162 int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx,
163 const unsigned char *d, long len)
164 {
165 int ret;
166 EVP_PKEY *pk;
167
168 pk = d2i_PrivateKey(0, NULL, &d, len);
169 if (!pk) {
170 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL");
171 goto failed1;
172 }
173
174 ret = SSL_CTX_use_PrivateKey(ctx, pk);
175 if (!ret) {
176 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_CTX_use_PrivateKey() return %d", ret);
177 goto failed2;
178 }
179
180 return 1;
181
182 failed2:
183 EVP_PKEY_free(pk);
184 failed1:
185 return 0;
186 }
187
188 /**
189 * @brief load private key into the SSL
190 */
SSL_use_PrivateKey_ASN1(int type,SSL * ssl,const unsigned char * d,long len)191 int SSL_use_PrivateKey_ASN1(int type, SSL *ssl,
192 const unsigned char *d, long len)
193 {
194 int ret;
195 EVP_PKEY *pk;
196
197 pk = d2i_PrivateKey(0, NULL, &d, len);
198 if (!pk) {
199 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL");
200 goto failed1;
201 }
202
203 ret = SSL_use_PrivateKey(ssl, pk);
204 if (!ret) {
205 SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_use_PrivateKey() return %d", ret);
206 goto failed2;
207 }
208
209 return 1;
210
211 failed2:
212 EVP_PKEY_free(pk);
213 failed1:
214 return 0;
215 }
216
217 /**
218 * @brief load the private key file into SSL context
219 */
SSL_CTX_use_PrivateKey_file(SSL_CTX * ctx,const char * file,int type)220 int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
221 {
222 return 0;
223 }
224
225 /**
226 * @brief load the private key file into SSL
227 */
SSL_use_PrivateKey_file(SSL_CTX * ctx,const char * file,int type)228 int SSL_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
229 {
230 return 0;
231 }
232
233 /**
234 * @brief load the RSA ASN1 private key into SSL context
235 */
SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX * ctx,const unsigned char * d,long len)236 int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len)
237 {
238 return SSL_CTX_use_PrivateKey_ASN1(0, ctx, d, len);
239 }
240