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