1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include "ssl_local.h" 12e1051a39Sopenharmony_ci#include "internal/packet.h" 13e1051a39Sopenharmony_ci#include <openssl/bio.h> 14e1051a39Sopenharmony_ci#include <openssl/objects.h> 15e1051a39Sopenharmony_ci#include <openssl/evp.h> 16e1051a39Sopenharmony_ci#include <openssl/x509.h> 17e1051a39Sopenharmony_ci#include <openssl/x509v3.h> 18e1051a39Sopenharmony_ci#include <openssl/pem.h> 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_cistatic int ssl_set_cert(CERT *c, X509 *x509); 21e1051a39Sopenharmony_cistatic int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); 22e1051a39Sopenharmony_ci 23e1051a39Sopenharmony_ci#define SYNTHV1CONTEXT (SSL_EXT_TLS1_2_AND_BELOW_ONLY \ 24e1051a39Sopenharmony_ci | SSL_EXT_CLIENT_HELLO \ 25e1051a39Sopenharmony_ci | SSL_EXT_TLS1_2_SERVER_HELLO \ 26e1051a39Sopenharmony_ci | SSL_EXT_IGNORE_ON_RESUMPTION) 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_ciint SSL_use_certificate(SSL *ssl, X509 *x) 29e1051a39Sopenharmony_ci{ 30e1051a39Sopenharmony_ci int rv; 31e1051a39Sopenharmony_ci if (x == NULL) { 32e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); 33e1051a39Sopenharmony_ci return 0; 34e1051a39Sopenharmony_ci } 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci rv = ssl_security_cert(ssl, NULL, x, 0, 1); 37e1051a39Sopenharmony_ci if (rv != 1) { 38e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, rv); 39e1051a39Sopenharmony_ci return 0; 40e1051a39Sopenharmony_ci } 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ci return ssl_set_cert(ssl->cert, x); 43e1051a39Sopenharmony_ci} 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_ciint SSL_use_certificate_file(SSL *ssl, const char *file, int type) 46e1051a39Sopenharmony_ci{ 47e1051a39Sopenharmony_ci int j; 48e1051a39Sopenharmony_ci BIO *in; 49e1051a39Sopenharmony_ci int ret = 0; 50e1051a39Sopenharmony_ci X509 *cert = NULL, *x = NULL; 51e1051a39Sopenharmony_ci 52e1051a39Sopenharmony_ci in = BIO_new(BIO_s_file()); 53e1051a39Sopenharmony_ci if (in == NULL) { 54e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB); 55e1051a39Sopenharmony_ci goto end; 56e1051a39Sopenharmony_ci } 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ci if (BIO_read_filename(in, file) <= 0) { 59e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB); 60e1051a39Sopenharmony_ci goto end; 61e1051a39Sopenharmony_ci } 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_ci if (type != SSL_FILETYPE_ASN1 && type != SSL_FILETYPE_PEM) { 64e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE); 65e1051a39Sopenharmony_ci goto end; 66e1051a39Sopenharmony_ci } 67e1051a39Sopenharmony_ci x = X509_new_ex(ssl->ctx->libctx, ssl->ctx->propq); 68e1051a39Sopenharmony_ci if (x == NULL) { 69e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 70e1051a39Sopenharmony_ci goto end; 71e1051a39Sopenharmony_ci } 72e1051a39Sopenharmony_ci if (type == SSL_FILETYPE_ASN1) { 73e1051a39Sopenharmony_ci j = ERR_R_ASN1_LIB; 74e1051a39Sopenharmony_ci cert = d2i_X509_bio(in, &x); 75e1051a39Sopenharmony_ci } else if (type == SSL_FILETYPE_PEM) { 76e1051a39Sopenharmony_ci j = ERR_R_PEM_LIB; 77e1051a39Sopenharmony_ci cert = PEM_read_bio_X509(in, &x, ssl->default_passwd_callback, 78e1051a39Sopenharmony_ci ssl->default_passwd_callback_userdata); 79e1051a39Sopenharmony_ci } else { 80e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE); 81e1051a39Sopenharmony_ci goto end; 82e1051a39Sopenharmony_ci } 83e1051a39Sopenharmony_ci 84e1051a39Sopenharmony_ci if (cert == NULL) { 85e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, j); 86e1051a39Sopenharmony_ci goto end; 87e1051a39Sopenharmony_ci } 88e1051a39Sopenharmony_ci 89e1051a39Sopenharmony_ci ret = SSL_use_certificate(ssl, x); 90e1051a39Sopenharmony_ci end: 91e1051a39Sopenharmony_ci X509_free(x); 92e1051a39Sopenharmony_ci BIO_free(in); 93e1051a39Sopenharmony_ci return ret; 94e1051a39Sopenharmony_ci} 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ciint SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len) 97e1051a39Sopenharmony_ci{ 98e1051a39Sopenharmony_ci X509 *x; 99e1051a39Sopenharmony_ci int ret; 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_ci x = X509_new_ex(ssl->ctx->libctx, ssl->ctx->propq); 102e1051a39Sopenharmony_ci if (x == NULL) { 103e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 104e1051a39Sopenharmony_ci return 0; 105e1051a39Sopenharmony_ci } 106e1051a39Sopenharmony_ci 107e1051a39Sopenharmony_ci if (d2i_X509(&x, &d, (long)len)== NULL) { 108e1051a39Sopenharmony_ci X509_free(x); 109e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_ASN1_LIB); 110e1051a39Sopenharmony_ci return 0; 111e1051a39Sopenharmony_ci } 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ci ret = SSL_use_certificate(ssl, x); 114e1051a39Sopenharmony_ci X509_free(x); 115e1051a39Sopenharmony_ci return ret; 116e1051a39Sopenharmony_ci} 117e1051a39Sopenharmony_ci 118e1051a39Sopenharmony_cistatic int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) 119e1051a39Sopenharmony_ci{ 120e1051a39Sopenharmony_ci size_t i; 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ci if (ssl_cert_lookup_by_pkey(pkey, &i) == NULL) { 123e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); 124e1051a39Sopenharmony_ci return 0; 125e1051a39Sopenharmony_ci } 126e1051a39Sopenharmony_ci 127e1051a39Sopenharmony_ci if (c->pkeys[i].x509 != NULL 128e1051a39Sopenharmony_ci && !X509_check_private_key(c->pkeys[i].x509, pkey)) 129e1051a39Sopenharmony_ci return 0; 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_ci EVP_PKEY_free(c->pkeys[i].privatekey); 132e1051a39Sopenharmony_ci EVP_PKEY_up_ref(pkey); 133e1051a39Sopenharmony_ci c->pkeys[i].privatekey = pkey; 134e1051a39Sopenharmony_ci c->key = &c->pkeys[i]; 135e1051a39Sopenharmony_ci return 1; 136e1051a39Sopenharmony_ci} 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ciint SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) 139e1051a39Sopenharmony_ci{ 140e1051a39Sopenharmony_ci int ret; 141e1051a39Sopenharmony_ci 142e1051a39Sopenharmony_ci if (pkey == NULL) { 143e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); 144e1051a39Sopenharmony_ci return 0; 145e1051a39Sopenharmony_ci } 146e1051a39Sopenharmony_ci ret = ssl_set_pkey(ssl->cert, pkey); 147e1051a39Sopenharmony_ci return ret; 148e1051a39Sopenharmony_ci} 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_ciint SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) 151e1051a39Sopenharmony_ci{ 152e1051a39Sopenharmony_ci int j, ret = 0; 153e1051a39Sopenharmony_ci BIO *in; 154e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 155e1051a39Sopenharmony_ci 156e1051a39Sopenharmony_ci in = BIO_new(BIO_s_file()); 157e1051a39Sopenharmony_ci if (in == NULL) { 158e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB); 159e1051a39Sopenharmony_ci goto end; 160e1051a39Sopenharmony_ci } 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ci if (BIO_read_filename(in, file) <= 0) { 163e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB); 164e1051a39Sopenharmony_ci goto end; 165e1051a39Sopenharmony_ci } 166e1051a39Sopenharmony_ci if (type == SSL_FILETYPE_PEM) { 167e1051a39Sopenharmony_ci j = ERR_R_PEM_LIB; 168e1051a39Sopenharmony_ci pkey = PEM_read_bio_PrivateKey_ex(in, NULL, 169e1051a39Sopenharmony_ci ssl->default_passwd_callback, 170e1051a39Sopenharmony_ci ssl->default_passwd_callback_userdata, 171e1051a39Sopenharmony_ci ssl->ctx->libctx, 172e1051a39Sopenharmony_ci ssl->ctx->propq); 173e1051a39Sopenharmony_ci } else if (type == SSL_FILETYPE_ASN1) { 174e1051a39Sopenharmony_ci j = ERR_R_ASN1_LIB; 175e1051a39Sopenharmony_ci pkey = d2i_PrivateKey_ex_bio(in, NULL, ssl->ctx->libctx, 176e1051a39Sopenharmony_ci ssl->ctx->propq); 177e1051a39Sopenharmony_ci } else { 178e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE); 179e1051a39Sopenharmony_ci goto end; 180e1051a39Sopenharmony_ci } 181e1051a39Sopenharmony_ci if (pkey == NULL) { 182e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, j); 183e1051a39Sopenharmony_ci goto end; 184e1051a39Sopenharmony_ci } 185e1051a39Sopenharmony_ci ret = SSL_use_PrivateKey(ssl, pkey); 186e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 187e1051a39Sopenharmony_ci end: 188e1051a39Sopenharmony_ci BIO_free(in); 189e1051a39Sopenharmony_ci return ret; 190e1051a39Sopenharmony_ci} 191e1051a39Sopenharmony_ci 192e1051a39Sopenharmony_ciint SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, 193e1051a39Sopenharmony_ci long len) 194e1051a39Sopenharmony_ci{ 195e1051a39Sopenharmony_ci int ret; 196e1051a39Sopenharmony_ci const unsigned char *p; 197e1051a39Sopenharmony_ci EVP_PKEY *pkey; 198e1051a39Sopenharmony_ci 199e1051a39Sopenharmony_ci p = d; 200e1051a39Sopenharmony_ci if ((pkey = d2i_PrivateKey_ex(type, NULL, &p, (long)len, ssl->ctx->libctx, 201e1051a39Sopenharmony_ci ssl->ctx->propq)) == NULL) { 202e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_ASN1_LIB); 203e1051a39Sopenharmony_ci return 0; 204e1051a39Sopenharmony_ci } 205e1051a39Sopenharmony_ci 206e1051a39Sopenharmony_ci ret = SSL_use_PrivateKey(ssl, pkey); 207e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 208e1051a39Sopenharmony_ci return ret; 209e1051a39Sopenharmony_ci} 210e1051a39Sopenharmony_ci 211e1051a39Sopenharmony_ciint SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) 212e1051a39Sopenharmony_ci{ 213e1051a39Sopenharmony_ci int rv; 214e1051a39Sopenharmony_ci if (x == NULL) { 215e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); 216e1051a39Sopenharmony_ci return 0; 217e1051a39Sopenharmony_ci } 218e1051a39Sopenharmony_ci 219e1051a39Sopenharmony_ci rv = ssl_security_cert(NULL, ctx, x, 0, 1); 220e1051a39Sopenharmony_ci if (rv != 1) { 221e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, rv); 222e1051a39Sopenharmony_ci return 0; 223e1051a39Sopenharmony_ci } 224e1051a39Sopenharmony_ci return ssl_set_cert(ctx->cert, x); 225e1051a39Sopenharmony_ci} 226e1051a39Sopenharmony_ci 227e1051a39Sopenharmony_cistatic int ssl_set_cert(CERT *c, X509 *x) 228e1051a39Sopenharmony_ci{ 229e1051a39Sopenharmony_ci EVP_PKEY *pkey; 230e1051a39Sopenharmony_ci size_t i; 231e1051a39Sopenharmony_ci 232e1051a39Sopenharmony_ci pkey = X509_get0_pubkey(x); 233e1051a39Sopenharmony_ci if (pkey == NULL) { 234e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_X509_LIB); 235e1051a39Sopenharmony_ci return 0; 236e1051a39Sopenharmony_ci } 237e1051a39Sopenharmony_ci 238e1051a39Sopenharmony_ci if (ssl_cert_lookup_by_pkey(pkey, &i) == NULL) { 239e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); 240e1051a39Sopenharmony_ci return 0; 241e1051a39Sopenharmony_ci } 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_ci if (i == SSL_PKEY_ECC && !EVP_PKEY_can_sign(pkey)) { 244e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING); 245e1051a39Sopenharmony_ci return 0; 246e1051a39Sopenharmony_ci } 247e1051a39Sopenharmony_ci 248e1051a39Sopenharmony_ci if (c->pkeys[i].privatekey != NULL) { 249e1051a39Sopenharmony_ci /* 250e1051a39Sopenharmony_ci * The return code from EVP_PKEY_copy_parameters is deliberately 251e1051a39Sopenharmony_ci * ignored. Some EVP_PKEY types cannot do this. 252e1051a39Sopenharmony_ci */ 253e1051a39Sopenharmony_ci EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey); 254e1051a39Sopenharmony_ci ERR_clear_error(); 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ci if (!X509_check_private_key(x, c->pkeys[i].privatekey)) { 257e1051a39Sopenharmony_ci /* 258e1051a39Sopenharmony_ci * don't fail for a cert/key mismatch, just free current private 259e1051a39Sopenharmony_ci * key (when switching to a different cert & key, first this 260e1051a39Sopenharmony_ci * function should be used, then ssl_set_pkey 261e1051a39Sopenharmony_ci */ 262e1051a39Sopenharmony_ci EVP_PKEY_free(c->pkeys[i].privatekey); 263e1051a39Sopenharmony_ci c->pkeys[i].privatekey = NULL; 264e1051a39Sopenharmony_ci /* clear error queue */ 265e1051a39Sopenharmony_ci ERR_clear_error(); 266e1051a39Sopenharmony_ci } 267e1051a39Sopenharmony_ci } 268e1051a39Sopenharmony_ci 269e1051a39Sopenharmony_ci X509_free(c->pkeys[i].x509); 270e1051a39Sopenharmony_ci X509_up_ref(x); 271e1051a39Sopenharmony_ci c->pkeys[i].x509 = x; 272e1051a39Sopenharmony_ci c->key = &(c->pkeys[i]); 273e1051a39Sopenharmony_ci 274e1051a39Sopenharmony_ci return 1; 275e1051a39Sopenharmony_ci} 276e1051a39Sopenharmony_ci 277e1051a39Sopenharmony_ciint SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) 278e1051a39Sopenharmony_ci{ 279e1051a39Sopenharmony_ci int j = SSL_R_BAD_VALUE; 280e1051a39Sopenharmony_ci BIO *in; 281e1051a39Sopenharmony_ci int ret = 0; 282e1051a39Sopenharmony_ci X509 *x = NULL, *cert = NULL; 283e1051a39Sopenharmony_ci 284e1051a39Sopenharmony_ci in = BIO_new(BIO_s_file()); 285e1051a39Sopenharmony_ci if (in == NULL) { 286e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB); 287e1051a39Sopenharmony_ci goto end; 288e1051a39Sopenharmony_ci } 289e1051a39Sopenharmony_ci 290e1051a39Sopenharmony_ci if (BIO_read_filename(in, file) <= 0) { 291e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB); 292e1051a39Sopenharmony_ci goto end; 293e1051a39Sopenharmony_ci } 294e1051a39Sopenharmony_ci if (type != SSL_FILETYPE_ASN1 && type != SSL_FILETYPE_PEM) { 295e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE); 296e1051a39Sopenharmony_ci goto end; 297e1051a39Sopenharmony_ci } 298e1051a39Sopenharmony_ci x = X509_new_ex(ctx->libctx, ctx->propq); 299e1051a39Sopenharmony_ci if (x == NULL) { 300e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 301e1051a39Sopenharmony_ci goto end; 302e1051a39Sopenharmony_ci } 303e1051a39Sopenharmony_ci if (type == SSL_FILETYPE_ASN1) { 304e1051a39Sopenharmony_ci j = ERR_R_ASN1_LIB; 305e1051a39Sopenharmony_ci cert = d2i_X509_bio(in, &x); 306e1051a39Sopenharmony_ci } else if (type == SSL_FILETYPE_PEM) { 307e1051a39Sopenharmony_ci j = ERR_R_PEM_LIB; 308e1051a39Sopenharmony_ci cert = PEM_read_bio_X509(in, &x, ctx->default_passwd_callback, 309e1051a39Sopenharmony_ci ctx->default_passwd_callback_userdata); 310e1051a39Sopenharmony_ci } 311e1051a39Sopenharmony_ci if (cert == NULL) { 312e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, j); 313e1051a39Sopenharmony_ci goto end; 314e1051a39Sopenharmony_ci } 315e1051a39Sopenharmony_ci 316e1051a39Sopenharmony_ci ret = SSL_CTX_use_certificate(ctx, x); 317e1051a39Sopenharmony_ci end: 318e1051a39Sopenharmony_ci X509_free(x); 319e1051a39Sopenharmony_ci BIO_free(in); 320e1051a39Sopenharmony_ci return ret; 321e1051a39Sopenharmony_ci} 322e1051a39Sopenharmony_ci 323e1051a39Sopenharmony_ciint SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d) 324e1051a39Sopenharmony_ci{ 325e1051a39Sopenharmony_ci X509 *x; 326e1051a39Sopenharmony_ci int ret; 327e1051a39Sopenharmony_ci 328e1051a39Sopenharmony_ci x = X509_new_ex(ctx->libctx, ctx->propq); 329e1051a39Sopenharmony_ci if (x == NULL) { 330e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 331e1051a39Sopenharmony_ci return 0; 332e1051a39Sopenharmony_ci } 333e1051a39Sopenharmony_ci 334e1051a39Sopenharmony_ci if (d2i_X509(&x, &d, (long)len) == NULL) { 335e1051a39Sopenharmony_ci X509_free(x); 336e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_ASN1_LIB); 337e1051a39Sopenharmony_ci return 0; 338e1051a39Sopenharmony_ci } 339e1051a39Sopenharmony_ci 340e1051a39Sopenharmony_ci ret = SSL_CTX_use_certificate(ctx, x); 341e1051a39Sopenharmony_ci X509_free(x); 342e1051a39Sopenharmony_ci return ret; 343e1051a39Sopenharmony_ci} 344e1051a39Sopenharmony_ci 345e1051a39Sopenharmony_ciint SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) 346e1051a39Sopenharmony_ci{ 347e1051a39Sopenharmony_ci if (pkey == NULL) { 348e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); 349e1051a39Sopenharmony_ci return 0; 350e1051a39Sopenharmony_ci } 351e1051a39Sopenharmony_ci return ssl_set_pkey(ctx->cert, pkey); 352e1051a39Sopenharmony_ci} 353e1051a39Sopenharmony_ci 354e1051a39Sopenharmony_ciint SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) 355e1051a39Sopenharmony_ci{ 356e1051a39Sopenharmony_ci int j, ret = 0; 357e1051a39Sopenharmony_ci BIO *in; 358e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 359e1051a39Sopenharmony_ci 360e1051a39Sopenharmony_ci in = BIO_new(BIO_s_file()); 361e1051a39Sopenharmony_ci if (in == NULL) { 362e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB); 363e1051a39Sopenharmony_ci goto end; 364e1051a39Sopenharmony_ci } 365e1051a39Sopenharmony_ci 366e1051a39Sopenharmony_ci if (BIO_read_filename(in, file) <= 0) { 367e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB); 368e1051a39Sopenharmony_ci goto end; 369e1051a39Sopenharmony_ci } 370e1051a39Sopenharmony_ci if (type == SSL_FILETYPE_PEM) { 371e1051a39Sopenharmony_ci j = ERR_R_PEM_LIB; 372e1051a39Sopenharmony_ci pkey = PEM_read_bio_PrivateKey_ex(in, NULL, 373e1051a39Sopenharmony_ci ctx->default_passwd_callback, 374e1051a39Sopenharmony_ci ctx->default_passwd_callback_userdata, 375e1051a39Sopenharmony_ci ctx->libctx, ctx->propq); 376e1051a39Sopenharmony_ci } else if (type == SSL_FILETYPE_ASN1) { 377e1051a39Sopenharmony_ci j = ERR_R_ASN1_LIB; 378e1051a39Sopenharmony_ci pkey = d2i_PrivateKey_ex_bio(in, NULL, ctx->libctx, ctx->propq); 379e1051a39Sopenharmony_ci } else { 380e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE); 381e1051a39Sopenharmony_ci goto end; 382e1051a39Sopenharmony_ci } 383e1051a39Sopenharmony_ci if (pkey == NULL) { 384e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, j); 385e1051a39Sopenharmony_ci goto end; 386e1051a39Sopenharmony_ci } 387e1051a39Sopenharmony_ci ret = SSL_CTX_use_PrivateKey(ctx, pkey); 388e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 389e1051a39Sopenharmony_ci end: 390e1051a39Sopenharmony_ci BIO_free(in); 391e1051a39Sopenharmony_ci return ret; 392e1051a39Sopenharmony_ci} 393e1051a39Sopenharmony_ci 394e1051a39Sopenharmony_ciint SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, 395e1051a39Sopenharmony_ci const unsigned char *d, long len) 396e1051a39Sopenharmony_ci{ 397e1051a39Sopenharmony_ci int ret; 398e1051a39Sopenharmony_ci const unsigned char *p; 399e1051a39Sopenharmony_ci EVP_PKEY *pkey; 400e1051a39Sopenharmony_ci 401e1051a39Sopenharmony_ci p = d; 402e1051a39Sopenharmony_ci if ((pkey = d2i_PrivateKey_ex(type, NULL, &p, (long)len, ctx->libctx, 403e1051a39Sopenharmony_ci ctx->propq)) == NULL) { 404e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_ASN1_LIB); 405e1051a39Sopenharmony_ci return 0; 406e1051a39Sopenharmony_ci } 407e1051a39Sopenharmony_ci 408e1051a39Sopenharmony_ci ret = SSL_CTX_use_PrivateKey(ctx, pkey); 409e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 410e1051a39Sopenharmony_ci return ret; 411e1051a39Sopenharmony_ci} 412e1051a39Sopenharmony_ci 413e1051a39Sopenharmony_ci/* 414e1051a39Sopenharmony_ci * Read a file that contains our certificate in "PEM" format, possibly 415e1051a39Sopenharmony_ci * followed by a sequence of CA certificates that should be sent to the peer 416e1051a39Sopenharmony_ci * in the Certificate message. 417e1051a39Sopenharmony_ci */ 418e1051a39Sopenharmony_cistatic int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file) 419e1051a39Sopenharmony_ci{ 420e1051a39Sopenharmony_ci BIO *in; 421e1051a39Sopenharmony_ci int ret = 0; 422e1051a39Sopenharmony_ci X509 *x = NULL; 423e1051a39Sopenharmony_ci pem_password_cb *passwd_callback; 424e1051a39Sopenharmony_ci void *passwd_callback_userdata; 425e1051a39Sopenharmony_ci SSL_CTX *real_ctx = (ssl == NULL) ? ctx : ssl->ctx; 426e1051a39Sopenharmony_ci 427e1051a39Sopenharmony_ci if (ctx == NULL && ssl == NULL) 428e1051a39Sopenharmony_ci return 0; 429e1051a39Sopenharmony_ci 430e1051a39Sopenharmony_ci ERR_clear_error(); /* clear error stack for 431e1051a39Sopenharmony_ci * SSL_CTX_use_certificate() */ 432e1051a39Sopenharmony_ci 433e1051a39Sopenharmony_ci if (ctx != NULL) { 434e1051a39Sopenharmony_ci passwd_callback = ctx->default_passwd_callback; 435e1051a39Sopenharmony_ci passwd_callback_userdata = ctx->default_passwd_callback_userdata; 436e1051a39Sopenharmony_ci } else { 437e1051a39Sopenharmony_ci passwd_callback = ssl->default_passwd_callback; 438e1051a39Sopenharmony_ci passwd_callback_userdata = ssl->default_passwd_callback_userdata; 439e1051a39Sopenharmony_ci } 440e1051a39Sopenharmony_ci 441e1051a39Sopenharmony_ci in = BIO_new(BIO_s_file()); 442e1051a39Sopenharmony_ci if (in == NULL) { 443e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB); 444e1051a39Sopenharmony_ci goto end; 445e1051a39Sopenharmony_ci } 446e1051a39Sopenharmony_ci 447e1051a39Sopenharmony_ci if (BIO_read_filename(in, file) <= 0) { 448e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB); 449e1051a39Sopenharmony_ci goto end; 450e1051a39Sopenharmony_ci } 451e1051a39Sopenharmony_ci 452e1051a39Sopenharmony_ci x = X509_new_ex(real_ctx->libctx, real_ctx->propq); 453e1051a39Sopenharmony_ci if (x == NULL) { 454e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 455e1051a39Sopenharmony_ci goto end; 456e1051a39Sopenharmony_ci } 457e1051a39Sopenharmony_ci if (PEM_read_bio_X509_AUX(in, &x, passwd_callback, 458e1051a39Sopenharmony_ci passwd_callback_userdata) == NULL) { 459e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_PEM_LIB); 460e1051a39Sopenharmony_ci goto end; 461e1051a39Sopenharmony_ci } 462e1051a39Sopenharmony_ci 463e1051a39Sopenharmony_ci if (ctx) 464e1051a39Sopenharmony_ci ret = SSL_CTX_use_certificate(ctx, x); 465e1051a39Sopenharmony_ci else 466e1051a39Sopenharmony_ci ret = SSL_use_certificate(ssl, x); 467e1051a39Sopenharmony_ci 468e1051a39Sopenharmony_ci if (ERR_peek_error() != 0) 469e1051a39Sopenharmony_ci ret = 0; /* Key/certificate mismatch doesn't imply 470e1051a39Sopenharmony_ci * ret==0 ... */ 471e1051a39Sopenharmony_ci if (ret) { 472e1051a39Sopenharmony_ci /* 473e1051a39Sopenharmony_ci * If we could set up our certificate, now proceed to the CA 474e1051a39Sopenharmony_ci * certificates. 475e1051a39Sopenharmony_ci */ 476e1051a39Sopenharmony_ci X509 *ca; 477e1051a39Sopenharmony_ci int r; 478e1051a39Sopenharmony_ci unsigned long err; 479e1051a39Sopenharmony_ci 480e1051a39Sopenharmony_ci if (ctx) 481e1051a39Sopenharmony_ci r = SSL_CTX_clear_chain_certs(ctx); 482e1051a39Sopenharmony_ci else 483e1051a39Sopenharmony_ci r = SSL_clear_chain_certs(ssl); 484e1051a39Sopenharmony_ci 485e1051a39Sopenharmony_ci if (r == 0) { 486e1051a39Sopenharmony_ci ret = 0; 487e1051a39Sopenharmony_ci goto end; 488e1051a39Sopenharmony_ci } 489e1051a39Sopenharmony_ci 490e1051a39Sopenharmony_ci while (1) { 491e1051a39Sopenharmony_ci ca = X509_new_ex(real_ctx->libctx, real_ctx->propq); 492e1051a39Sopenharmony_ci if (ca == NULL) { 493e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 494e1051a39Sopenharmony_ci goto end; 495e1051a39Sopenharmony_ci } 496e1051a39Sopenharmony_ci if (PEM_read_bio_X509(in, &ca, passwd_callback, 497e1051a39Sopenharmony_ci passwd_callback_userdata) != NULL) { 498e1051a39Sopenharmony_ci if (ctx) 499e1051a39Sopenharmony_ci r = SSL_CTX_add0_chain_cert(ctx, ca); 500e1051a39Sopenharmony_ci else 501e1051a39Sopenharmony_ci r = SSL_add0_chain_cert(ssl, ca); 502e1051a39Sopenharmony_ci /* 503e1051a39Sopenharmony_ci * Note that we must not free ca if it was successfully added to 504e1051a39Sopenharmony_ci * the chain (while we must free the main certificate, since its 505e1051a39Sopenharmony_ci * reference count is increased by SSL_CTX_use_certificate). 506e1051a39Sopenharmony_ci */ 507e1051a39Sopenharmony_ci if (!r) { 508e1051a39Sopenharmony_ci X509_free(ca); 509e1051a39Sopenharmony_ci ret = 0; 510e1051a39Sopenharmony_ci goto end; 511e1051a39Sopenharmony_ci } 512e1051a39Sopenharmony_ci } else { 513e1051a39Sopenharmony_ci X509_free(ca); 514e1051a39Sopenharmony_ci break; 515e1051a39Sopenharmony_ci } 516e1051a39Sopenharmony_ci } 517e1051a39Sopenharmony_ci /* When the while loop ends, it's usually just EOF. */ 518e1051a39Sopenharmony_ci err = ERR_peek_last_error(); 519e1051a39Sopenharmony_ci if (ERR_GET_LIB(err) == ERR_LIB_PEM 520e1051a39Sopenharmony_ci && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) 521e1051a39Sopenharmony_ci ERR_clear_error(); 522e1051a39Sopenharmony_ci else 523e1051a39Sopenharmony_ci ret = 0; /* some real error */ 524e1051a39Sopenharmony_ci } 525e1051a39Sopenharmony_ci 526e1051a39Sopenharmony_ci end: 527e1051a39Sopenharmony_ci X509_free(x); 528e1051a39Sopenharmony_ci BIO_free(in); 529e1051a39Sopenharmony_ci return ret; 530e1051a39Sopenharmony_ci} 531e1051a39Sopenharmony_ci 532e1051a39Sopenharmony_ciint SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) 533e1051a39Sopenharmony_ci{ 534e1051a39Sopenharmony_ci return use_certificate_chain_file(ctx, NULL, file); 535e1051a39Sopenharmony_ci} 536e1051a39Sopenharmony_ci 537e1051a39Sopenharmony_ciint SSL_use_certificate_chain_file(SSL *ssl, const char *file) 538e1051a39Sopenharmony_ci{ 539e1051a39Sopenharmony_ci return use_certificate_chain_file(NULL, ssl, file); 540e1051a39Sopenharmony_ci} 541e1051a39Sopenharmony_ci 542e1051a39Sopenharmony_cistatic int serverinfo_find_extension(const unsigned char *serverinfo, 543e1051a39Sopenharmony_ci size_t serverinfo_length, 544e1051a39Sopenharmony_ci unsigned int extension_type, 545e1051a39Sopenharmony_ci const unsigned char **extension_data, 546e1051a39Sopenharmony_ci size_t *extension_length) 547e1051a39Sopenharmony_ci{ 548e1051a39Sopenharmony_ci PACKET pkt, data; 549e1051a39Sopenharmony_ci 550e1051a39Sopenharmony_ci *extension_data = NULL; 551e1051a39Sopenharmony_ci *extension_length = 0; 552e1051a39Sopenharmony_ci if (serverinfo == NULL || serverinfo_length == 0) 553e1051a39Sopenharmony_ci return -1; 554e1051a39Sopenharmony_ci 555e1051a39Sopenharmony_ci if (!PACKET_buf_init(&pkt, serverinfo, serverinfo_length)) 556e1051a39Sopenharmony_ci return -1; 557e1051a39Sopenharmony_ci 558e1051a39Sopenharmony_ci for (;;) { 559e1051a39Sopenharmony_ci unsigned int type = 0; 560e1051a39Sopenharmony_ci unsigned long context = 0; 561e1051a39Sopenharmony_ci 562e1051a39Sopenharmony_ci /* end of serverinfo */ 563e1051a39Sopenharmony_ci if (PACKET_remaining(&pkt) == 0) 564e1051a39Sopenharmony_ci return 0; /* Extension not found */ 565e1051a39Sopenharmony_ci 566e1051a39Sopenharmony_ci if (!PACKET_get_net_4(&pkt, &context) 567e1051a39Sopenharmony_ci || !PACKET_get_net_2(&pkt, &type) 568e1051a39Sopenharmony_ci || !PACKET_get_length_prefixed_2(&pkt, &data)) 569e1051a39Sopenharmony_ci return -1; 570e1051a39Sopenharmony_ci 571e1051a39Sopenharmony_ci if (type == extension_type) { 572e1051a39Sopenharmony_ci *extension_data = PACKET_data(&data); 573e1051a39Sopenharmony_ci *extension_length = PACKET_remaining(&data);; 574e1051a39Sopenharmony_ci return 1; /* Success */ 575e1051a39Sopenharmony_ci } 576e1051a39Sopenharmony_ci } 577e1051a39Sopenharmony_ci /* Unreachable */ 578e1051a39Sopenharmony_ci} 579e1051a39Sopenharmony_ci 580e1051a39Sopenharmony_cistatic int serverinfoex_srv_parse_cb(SSL *s, unsigned int ext_type, 581e1051a39Sopenharmony_ci unsigned int context, 582e1051a39Sopenharmony_ci const unsigned char *in, 583e1051a39Sopenharmony_ci size_t inlen, X509 *x, size_t chainidx, 584e1051a39Sopenharmony_ci int *al, void *arg) 585e1051a39Sopenharmony_ci{ 586e1051a39Sopenharmony_ci 587e1051a39Sopenharmony_ci if (inlen != 0) { 588e1051a39Sopenharmony_ci *al = SSL_AD_DECODE_ERROR; 589e1051a39Sopenharmony_ci return 0; 590e1051a39Sopenharmony_ci } 591e1051a39Sopenharmony_ci 592e1051a39Sopenharmony_ci return 1; 593e1051a39Sopenharmony_ci} 594e1051a39Sopenharmony_ci 595e1051a39Sopenharmony_cistatic int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type, 596e1051a39Sopenharmony_ci const unsigned char *in, 597e1051a39Sopenharmony_ci size_t inlen, int *al, void *arg) 598e1051a39Sopenharmony_ci{ 599e1051a39Sopenharmony_ci return serverinfoex_srv_parse_cb(s, ext_type, 0, in, inlen, NULL, 0, al, 600e1051a39Sopenharmony_ci arg); 601e1051a39Sopenharmony_ci} 602e1051a39Sopenharmony_ci 603e1051a39Sopenharmony_cistatic int serverinfoex_srv_add_cb(SSL *s, unsigned int ext_type, 604e1051a39Sopenharmony_ci unsigned int context, 605e1051a39Sopenharmony_ci const unsigned char **out, 606e1051a39Sopenharmony_ci size_t *outlen, X509 *x, size_t chainidx, 607e1051a39Sopenharmony_ci int *al, void *arg) 608e1051a39Sopenharmony_ci{ 609e1051a39Sopenharmony_ci const unsigned char *serverinfo = NULL; 610e1051a39Sopenharmony_ci size_t serverinfo_length = 0; 611e1051a39Sopenharmony_ci 612e1051a39Sopenharmony_ci /* We only support extensions for the first Certificate */ 613e1051a39Sopenharmony_ci if ((context & SSL_EXT_TLS1_3_CERTIFICATE) != 0 && chainidx > 0) 614e1051a39Sopenharmony_ci return 0; 615e1051a39Sopenharmony_ci 616e1051a39Sopenharmony_ci /* Is there serverinfo data for the chosen server cert? */ 617e1051a39Sopenharmony_ci if ((ssl_get_server_cert_serverinfo(s, &serverinfo, 618e1051a39Sopenharmony_ci &serverinfo_length)) != 0) { 619e1051a39Sopenharmony_ci /* Find the relevant extension from the serverinfo */ 620e1051a39Sopenharmony_ci int retval = serverinfo_find_extension(serverinfo, serverinfo_length, 621e1051a39Sopenharmony_ci ext_type, out, outlen); 622e1051a39Sopenharmony_ci if (retval == -1) { 623e1051a39Sopenharmony_ci *al = SSL_AD_INTERNAL_ERROR; 624e1051a39Sopenharmony_ci return -1; /* Error */ 625e1051a39Sopenharmony_ci } 626e1051a39Sopenharmony_ci if (retval == 0) 627e1051a39Sopenharmony_ci return 0; /* No extension found, don't send extension */ 628e1051a39Sopenharmony_ci return 1; /* Send extension */ 629e1051a39Sopenharmony_ci } 630e1051a39Sopenharmony_ci return 0; /* No serverinfo data found, don't send 631e1051a39Sopenharmony_ci * extension */ 632e1051a39Sopenharmony_ci} 633e1051a39Sopenharmony_ci 634e1051a39Sopenharmony_cistatic int serverinfo_srv_add_cb(SSL *s, unsigned int ext_type, 635e1051a39Sopenharmony_ci const unsigned char **out, size_t *outlen, 636e1051a39Sopenharmony_ci int *al, void *arg) 637e1051a39Sopenharmony_ci{ 638e1051a39Sopenharmony_ci return serverinfoex_srv_add_cb(s, ext_type, 0, out, outlen, NULL, 0, al, 639e1051a39Sopenharmony_ci arg); 640e1051a39Sopenharmony_ci} 641e1051a39Sopenharmony_ci 642e1051a39Sopenharmony_ci/* 643e1051a39Sopenharmony_ci * With a NULL context, this function just checks that the serverinfo data 644e1051a39Sopenharmony_ci * parses correctly. With a non-NULL context, it registers callbacks for 645e1051a39Sopenharmony_ci * the included extensions. 646e1051a39Sopenharmony_ci */ 647e1051a39Sopenharmony_cistatic int serverinfo_process_buffer(unsigned int version, 648e1051a39Sopenharmony_ci const unsigned char *serverinfo, 649e1051a39Sopenharmony_ci size_t serverinfo_length, SSL_CTX *ctx) 650e1051a39Sopenharmony_ci{ 651e1051a39Sopenharmony_ci PACKET pkt; 652e1051a39Sopenharmony_ci 653e1051a39Sopenharmony_ci if (serverinfo == NULL || serverinfo_length == 0) 654e1051a39Sopenharmony_ci return 0; 655e1051a39Sopenharmony_ci 656e1051a39Sopenharmony_ci if (version != SSL_SERVERINFOV1 && version != SSL_SERVERINFOV2) 657e1051a39Sopenharmony_ci return 0; 658e1051a39Sopenharmony_ci 659e1051a39Sopenharmony_ci if (!PACKET_buf_init(&pkt, serverinfo, serverinfo_length)) 660e1051a39Sopenharmony_ci return 0; 661e1051a39Sopenharmony_ci 662e1051a39Sopenharmony_ci while (PACKET_remaining(&pkt)) { 663e1051a39Sopenharmony_ci unsigned long context = 0; 664e1051a39Sopenharmony_ci unsigned int ext_type = 0; 665e1051a39Sopenharmony_ci PACKET data; 666e1051a39Sopenharmony_ci 667e1051a39Sopenharmony_ci if ((version == SSL_SERVERINFOV2 && !PACKET_get_net_4(&pkt, &context)) 668e1051a39Sopenharmony_ci || !PACKET_get_net_2(&pkt, &ext_type) 669e1051a39Sopenharmony_ci || !PACKET_get_length_prefixed_2(&pkt, &data)) 670e1051a39Sopenharmony_ci return 0; 671e1051a39Sopenharmony_ci 672e1051a39Sopenharmony_ci if (ctx == NULL) 673e1051a39Sopenharmony_ci continue; 674e1051a39Sopenharmony_ci 675e1051a39Sopenharmony_ci /* 676e1051a39Sopenharmony_ci * The old style custom extensions API could be set separately for 677e1051a39Sopenharmony_ci * server/client, i.e. you could set one custom extension for a client, 678e1051a39Sopenharmony_ci * and *for the same extension in the same SSL_CTX* you could set a 679e1051a39Sopenharmony_ci * custom extension for the server as well. It seems quite weird to be 680e1051a39Sopenharmony_ci * setting a custom extension for both client and server in a single 681e1051a39Sopenharmony_ci * SSL_CTX - but theoretically possible. This isn't possible in the 682e1051a39Sopenharmony_ci * new API. Therefore, if we have V1 serverinfo we use the old API. We 683e1051a39Sopenharmony_ci * also use the old API even if we have V2 serverinfo but the context 684e1051a39Sopenharmony_ci * looks like an old style <= TLSv1.2 extension. 685e1051a39Sopenharmony_ci */ 686e1051a39Sopenharmony_ci if (version == SSL_SERVERINFOV1 || context == SYNTHV1CONTEXT) { 687e1051a39Sopenharmony_ci if (!SSL_CTX_add_server_custom_ext(ctx, ext_type, 688e1051a39Sopenharmony_ci serverinfo_srv_add_cb, 689e1051a39Sopenharmony_ci NULL, NULL, 690e1051a39Sopenharmony_ci serverinfo_srv_parse_cb, 691e1051a39Sopenharmony_ci NULL)) 692e1051a39Sopenharmony_ci return 0; 693e1051a39Sopenharmony_ci } else { 694e1051a39Sopenharmony_ci if (!SSL_CTX_add_custom_ext(ctx, ext_type, context, 695e1051a39Sopenharmony_ci serverinfoex_srv_add_cb, 696e1051a39Sopenharmony_ci NULL, NULL, 697e1051a39Sopenharmony_ci serverinfoex_srv_parse_cb, 698e1051a39Sopenharmony_ci NULL)) 699e1051a39Sopenharmony_ci return 0; 700e1051a39Sopenharmony_ci } 701e1051a39Sopenharmony_ci } 702e1051a39Sopenharmony_ci 703e1051a39Sopenharmony_ci return 1; 704e1051a39Sopenharmony_ci} 705e1051a39Sopenharmony_ci 706e1051a39Sopenharmony_cistatic size_t extension_contextoff(unsigned int version) 707e1051a39Sopenharmony_ci{ 708e1051a39Sopenharmony_ci return version == SSL_SERVERINFOV1 ? 4 : 0; 709e1051a39Sopenharmony_ci} 710e1051a39Sopenharmony_ci 711e1051a39Sopenharmony_cistatic size_t extension_append_length(unsigned int version, size_t extension_length) 712e1051a39Sopenharmony_ci{ 713e1051a39Sopenharmony_ci return extension_length + extension_contextoff(version); 714e1051a39Sopenharmony_ci} 715e1051a39Sopenharmony_ci 716e1051a39Sopenharmony_cistatic void extension_append(unsigned int version, 717e1051a39Sopenharmony_ci const unsigned char *extension, 718e1051a39Sopenharmony_ci const size_t extension_length, 719e1051a39Sopenharmony_ci unsigned char *serverinfo) 720e1051a39Sopenharmony_ci{ 721e1051a39Sopenharmony_ci const size_t contextoff = extension_contextoff(version); 722e1051a39Sopenharmony_ci 723e1051a39Sopenharmony_ci if (contextoff > 0) { 724e1051a39Sopenharmony_ci /* We know this only uses the last 2 bytes */ 725e1051a39Sopenharmony_ci serverinfo[0] = 0; 726e1051a39Sopenharmony_ci serverinfo[1] = 0; 727e1051a39Sopenharmony_ci serverinfo[2] = (SYNTHV1CONTEXT >> 8) & 0xff; 728e1051a39Sopenharmony_ci serverinfo[3] = SYNTHV1CONTEXT & 0xff; 729e1051a39Sopenharmony_ci } 730e1051a39Sopenharmony_ci 731e1051a39Sopenharmony_ci memcpy(serverinfo + contextoff, extension, extension_length); 732e1051a39Sopenharmony_ci} 733e1051a39Sopenharmony_ci 734e1051a39Sopenharmony_ciint SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version, 735e1051a39Sopenharmony_ci const unsigned char *serverinfo, 736e1051a39Sopenharmony_ci size_t serverinfo_length) 737e1051a39Sopenharmony_ci{ 738e1051a39Sopenharmony_ci unsigned char *new_serverinfo = NULL; 739e1051a39Sopenharmony_ci 740e1051a39Sopenharmony_ci if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) { 741e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); 742e1051a39Sopenharmony_ci return 0; 743e1051a39Sopenharmony_ci } 744e1051a39Sopenharmony_ci if (version == SSL_SERVERINFOV1) { 745e1051a39Sopenharmony_ci /* 746e1051a39Sopenharmony_ci * Convert serverinfo version v1 to v2 and call yourself recursively 747e1051a39Sopenharmony_ci * over the converted serverinfo. 748e1051a39Sopenharmony_ci */ 749e1051a39Sopenharmony_ci const size_t sinfo_length = extension_append_length(SSL_SERVERINFOV1, 750e1051a39Sopenharmony_ci serverinfo_length); 751e1051a39Sopenharmony_ci unsigned char *sinfo; 752e1051a39Sopenharmony_ci int ret; 753e1051a39Sopenharmony_ci 754e1051a39Sopenharmony_ci sinfo = OPENSSL_malloc(sinfo_length); 755e1051a39Sopenharmony_ci if (sinfo == NULL) { 756e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 757e1051a39Sopenharmony_ci return 0; 758e1051a39Sopenharmony_ci } 759e1051a39Sopenharmony_ci 760e1051a39Sopenharmony_ci extension_append(SSL_SERVERINFOV1, serverinfo, serverinfo_length, sinfo); 761e1051a39Sopenharmony_ci 762e1051a39Sopenharmony_ci ret = SSL_CTX_use_serverinfo_ex(ctx, SSL_SERVERINFOV2, sinfo, 763e1051a39Sopenharmony_ci sinfo_length); 764e1051a39Sopenharmony_ci 765e1051a39Sopenharmony_ci OPENSSL_free(sinfo); 766e1051a39Sopenharmony_ci return ret; 767e1051a39Sopenharmony_ci } 768e1051a39Sopenharmony_ci if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length, 769e1051a39Sopenharmony_ci NULL)) { 770e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_SERVERINFO_DATA); 771e1051a39Sopenharmony_ci return 0; 772e1051a39Sopenharmony_ci } 773e1051a39Sopenharmony_ci if (ctx->cert->key == NULL) { 774e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); 775e1051a39Sopenharmony_ci return 0; 776e1051a39Sopenharmony_ci } 777e1051a39Sopenharmony_ci new_serverinfo = OPENSSL_realloc(ctx->cert->key->serverinfo, 778e1051a39Sopenharmony_ci serverinfo_length); 779e1051a39Sopenharmony_ci if (new_serverinfo == NULL) { 780e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 781e1051a39Sopenharmony_ci return 0; 782e1051a39Sopenharmony_ci } 783e1051a39Sopenharmony_ci ctx->cert->key->serverinfo = new_serverinfo; 784e1051a39Sopenharmony_ci memcpy(ctx->cert->key->serverinfo, serverinfo, serverinfo_length); 785e1051a39Sopenharmony_ci ctx->cert->key->serverinfo_length = serverinfo_length; 786e1051a39Sopenharmony_ci 787e1051a39Sopenharmony_ci /* 788e1051a39Sopenharmony_ci * Now that the serverinfo is validated and stored, go ahead and 789e1051a39Sopenharmony_ci * register callbacks. 790e1051a39Sopenharmony_ci */ 791e1051a39Sopenharmony_ci if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length, 792e1051a39Sopenharmony_ci ctx)) { 793e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_SERVERINFO_DATA); 794e1051a39Sopenharmony_ci return 0; 795e1051a39Sopenharmony_ci } 796e1051a39Sopenharmony_ci return 1; 797e1051a39Sopenharmony_ci} 798e1051a39Sopenharmony_ci 799e1051a39Sopenharmony_ciint SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, 800e1051a39Sopenharmony_ci size_t serverinfo_length) 801e1051a39Sopenharmony_ci{ 802e1051a39Sopenharmony_ci return SSL_CTX_use_serverinfo_ex(ctx, SSL_SERVERINFOV1, serverinfo, 803e1051a39Sopenharmony_ci serverinfo_length); 804e1051a39Sopenharmony_ci} 805e1051a39Sopenharmony_ci 806e1051a39Sopenharmony_ciint SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) 807e1051a39Sopenharmony_ci{ 808e1051a39Sopenharmony_ci unsigned char *serverinfo = NULL; 809e1051a39Sopenharmony_ci unsigned char *tmp; 810e1051a39Sopenharmony_ci size_t serverinfo_length = 0; 811e1051a39Sopenharmony_ci unsigned char *extension = 0; 812e1051a39Sopenharmony_ci long extension_length = 0; 813e1051a39Sopenharmony_ci char *name = NULL; 814e1051a39Sopenharmony_ci char *header = NULL; 815e1051a39Sopenharmony_ci static const char namePrefix1[] = "SERVERINFO FOR "; 816e1051a39Sopenharmony_ci static const char namePrefix2[] = "SERVERINFOV2 FOR "; 817e1051a39Sopenharmony_ci unsigned int name_len; 818e1051a39Sopenharmony_ci int ret = 0; 819e1051a39Sopenharmony_ci BIO *bin = NULL; 820e1051a39Sopenharmony_ci size_t num_extensions = 0; 821e1051a39Sopenharmony_ci 822e1051a39Sopenharmony_ci if (ctx == NULL || file == NULL) { 823e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); 824e1051a39Sopenharmony_ci goto end; 825e1051a39Sopenharmony_ci } 826e1051a39Sopenharmony_ci 827e1051a39Sopenharmony_ci bin = BIO_new(BIO_s_file()); 828e1051a39Sopenharmony_ci if (bin == NULL) { 829e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB); 830e1051a39Sopenharmony_ci goto end; 831e1051a39Sopenharmony_ci } 832e1051a39Sopenharmony_ci if (BIO_read_filename(bin, file) <= 0) { 833e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB); 834e1051a39Sopenharmony_ci goto end; 835e1051a39Sopenharmony_ci } 836e1051a39Sopenharmony_ci 837e1051a39Sopenharmony_ci for (num_extensions = 0;; num_extensions++) { 838e1051a39Sopenharmony_ci unsigned int version; 839e1051a39Sopenharmony_ci size_t append_length; 840e1051a39Sopenharmony_ci 841e1051a39Sopenharmony_ci if (PEM_read_bio(bin, &name, &header, &extension, &extension_length) 842e1051a39Sopenharmony_ci == 0) { 843e1051a39Sopenharmony_ci /* 844e1051a39Sopenharmony_ci * There must be at least one extension in this file 845e1051a39Sopenharmony_ci */ 846e1051a39Sopenharmony_ci if (num_extensions == 0) { 847e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_NO_PEM_EXTENSIONS); 848e1051a39Sopenharmony_ci goto end; 849e1051a39Sopenharmony_ci } else /* End of file, we're done */ 850e1051a39Sopenharmony_ci break; 851e1051a39Sopenharmony_ci } 852e1051a39Sopenharmony_ci /* Check that PEM name starts with "BEGIN SERVERINFO FOR " */ 853e1051a39Sopenharmony_ci name_len = strlen(name); 854e1051a39Sopenharmony_ci if (name_len < sizeof(namePrefix1) - 1) { 855e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_PEM_NAME_TOO_SHORT); 856e1051a39Sopenharmony_ci goto end; 857e1051a39Sopenharmony_ci } 858e1051a39Sopenharmony_ci if (strncmp(name, namePrefix1, sizeof(namePrefix1) - 1) == 0) { 859e1051a39Sopenharmony_ci version = SSL_SERVERINFOV1; 860e1051a39Sopenharmony_ci } else { 861e1051a39Sopenharmony_ci if (name_len < sizeof(namePrefix2) - 1) { 862e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_PEM_NAME_TOO_SHORT); 863e1051a39Sopenharmony_ci goto end; 864e1051a39Sopenharmony_ci } 865e1051a39Sopenharmony_ci if (strncmp(name, namePrefix2, sizeof(namePrefix2) - 1) != 0) { 866e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_PEM_NAME_BAD_PREFIX); 867e1051a39Sopenharmony_ci goto end; 868e1051a39Sopenharmony_ci } 869e1051a39Sopenharmony_ci version = SSL_SERVERINFOV2; 870e1051a39Sopenharmony_ci } 871e1051a39Sopenharmony_ci /* 872e1051a39Sopenharmony_ci * Check that the decoded PEM data is plausible (valid length field) 873e1051a39Sopenharmony_ci */ 874e1051a39Sopenharmony_ci if (version == SSL_SERVERINFOV1) { 875e1051a39Sopenharmony_ci /* 4 byte header: 2 bytes type, 2 bytes len */ 876e1051a39Sopenharmony_ci if (extension_length < 4 877e1051a39Sopenharmony_ci || (extension[2] << 8) + extension[3] 878e1051a39Sopenharmony_ci != extension_length - 4) { 879e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_BAD_DATA); 880e1051a39Sopenharmony_ci goto end; 881e1051a39Sopenharmony_ci } 882e1051a39Sopenharmony_ci } else { 883e1051a39Sopenharmony_ci /* 8 byte header: 4 bytes context, 2 bytes type, 2 bytes len */ 884e1051a39Sopenharmony_ci if (extension_length < 8 885e1051a39Sopenharmony_ci || (extension[6] << 8) + extension[7] 886e1051a39Sopenharmony_ci != extension_length - 8) { 887e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_BAD_DATA); 888e1051a39Sopenharmony_ci goto end; 889e1051a39Sopenharmony_ci } 890e1051a39Sopenharmony_ci } 891e1051a39Sopenharmony_ci /* Append the decoded extension to the serverinfo buffer */ 892e1051a39Sopenharmony_ci append_length = extension_append_length(version, extension_length); 893e1051a39Sopenharmony_ci tmp = OPENSSL_realloc(serverinfo, serverinfo_length + append_length); 894e1051a39Sopenharmony_ci if (tmp == NULL) { 895e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 896e1051a39Sopenharmony_ci goto end; 897e1051a39Sopenharmony_ci } 898e1051a39Sopenharmony_ci serverinfo = tmp; 899e1051a39Sopenharmony_ci extension_append(version, extension, extension_length, 900e1051a39Sopenharmony_ci serverinfo + serverinfo_length); 901e1051a39Sopenharmony_ci serverinfo_length += append_length; 902e1051a39Sopenharmony_ci 903e1051a39Sopenharmony_ci OPENSSL_free(name); 904e1051a39Sopenharmony_ci name = NULL; 905e1051a39Sopenharmony_ci OPENSSL_free(header); 906e1051a39Sopenharmony_ci header = NULL; 907e1051a39Sopenharmony_ci OPENSSL_free(extension); 908e1051a39Sopenharmony_ci extension = NULL; 909e1051a39Sopenharmony_ci } 910e1051a39Sopenharmony_ci 911e1051a39Sopenharmony_ci ret = SSL_CTX_use_serverinfo_ex(ctx, SSL_SERVERINFOV2, serverinfo, 912e1051a39Sopenharmony_ci serverinfo_length); 913e1051a39Sopenharmony_ci end: 914e1051a39Sopenharmony_ci /* SSL_CTX_use_serverinfo makes a local copy of the serverinfo. */ 915e1051a39Sopenharmony_ci OPENSSL_free(name); 916e1051a39Sopenharmony_ci OPENSSL_free(header); 917e1051a39Sopenharmony_ci OPENSSL_free(extension); 918e1051a39Sopenharmony_ci OPENSSL_free(serverinfo); 919e1051a39Sopenharmony_ci BIO_free(bin); 920e1051a39Sopenharmony_ci return ret; 921e1051a39Sopenharmony_ci} 922e1051a39Sopenharmony_ci 923e1051a39Sopenharmony_cistatic int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey, 924e1051a39Sopenharmony_ci STACK_OF(X509) *chain, int override) 925e1051a39Sopenharmony_ci{ 926e1051a39Sopenharmony_ci int ret = 0; 927e1051a39Sopenharmony_ci size_t i; 928e1051a39Sopenharmony_ci int j; 929e1051a39Sopenharmony_ci int rv; 930e1051a39Sopenharmony_ci CERT *c = ssl != NULL ? ssl->cert : ctx->cert; 931e1051a39Sopenharmony_ci STACK_OF(X509) *dup_chain = NULL; 932e1051a39Sopenharmony_ci EVP_PKEY *pubkey = NULL; 933e1051a39Sopenharmony_ci 934e1051a39Sopenharmony_ci /* Do all security checks before anything else */ 935e1051a39Sopenharmony_ci rv = ssl_security_cert(ssl, ctx, x509, 0, 1); 936e1051a39Sopenharmony_ci if (rv != 1) { 937e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, rv); 938e1051a39Sopenharmony_ci goto out; 939e1051a39Sopenharmony_ci } 940e1051a39Sopenharmony_ci for (j = 0; j < sk_X509_num(chain); j++) { 941e1051a39Sopenharmony_ci rv = ssl_security_cert(ssl, ctx, sk_X509_value(chain, j), 0, 0); 942e1051a39Sopenharmony_ci if (rv != 1) { 943e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, rv); 944e1051a39Sopenharmony_ci goto out; 945e1051a39Sopenharmony_ci } 946e1051a39Sopenharmony_ci } 947e1051a39Sopenharmony_ci 948e1051a39Sopenharmony_ci pubkey = X509_get_pubkey(x509); /* bumps reference */ 949e1051a39Sopenharmony_ci if (pubkey == NULL) 950e1051a39Sopenharmony_ci goto out; 951e1051a39Sopenharmony_ci if (privatekey == NULL) { 952e1051a39Sopenharmony_ci privatekey = pubkey; 953e1051a39Sopenharmony_ci } else { 954e1051a39Sopenharmony_ci /* For RSA, which has no parameters, missing returns 0 */ 955e1051a39Sopenharmony_ci if (EVP_PKEY_missing_parameters(privatekey)) { 956e1051a39Sopenharmony_ci if (EVP_PKEY_missing_parameters(pubkey)) { 957e1051a39Sopenharmony_ci /* nobody has parameters? - error */ 958e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_MISSING_PARAMETERS); 959e1051a39Sopenharmony_ci goto out; 960e1051a39Sopenharmony_ci } else { 961e1051a39Sopenharmony_ci /* copy to privatekey from pubkey */ 962e1051a39Sopenharmony_ci if (!EVP_PKEY_copy_parameters(privatekey, pubkey)) { 963e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_COPY_PARAMETERS_FAILED); 964e1051a39Sopenharmony_ci goto out; 965e1051a39Sopenharmony_ci } 966e1051a39Sopenharmony_ci } 967e1051a39Sopenharmony_ci } else if (EVP_PKEY_missing_parameters(pubkey)) { 968e1051a39Sopenharmony_ci /* copy to pubkey from privatekey */ 969e1051a39Sopenharmony_ci if (!EVP_PKEY_copy_parameters(pubkey, privatekey)) { 970e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_COPY_PARAMETERS_FAILED); 971e1051a39Sopenharmony_ci goto out; 972e1051a39Sopenharmony_ci } 973e1051a39Sopenharmony_ci } /* else both have parameters */ 974e1051a39Sopenharmony_ci 975e1051a39Sopenharmony_ci /* check that key <-> cert match */ 976e1051a39Sopenharmony_ci if (EVP_PKEY_eq(pubkey, privatekey) != 1) { 977e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_PRIVATE_KEY_MISMATCH); 978e1051a39Sopenharmony_ci goto out; 979e1051a39Sopenharmony_ci } 980e1051a39Sopenharmony_ci } 981e1051a39Sopenharmony_ci if (ssl_cert_lookup_by_pkey(pubkey, &i) == NULL) { 982e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); 983e1051a39Sopenharmony_ci goto out; 984e1051a39Sopenharmony_ci } 985e1051a39Sopenharmony_ci 986e1051a39Sopenharmony_ci if (!override && (c->pkeys[i].x509 != NULL 987e1051a39Sopenharmony_ci || c->pkeys[i].privatekey != NULL 988e1051a39Sopenharmony_ci || c->pkeys[i].chain != NULL)) { 989e1051a39Sopenharmony_ci /* No override, and something already there */ 990e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_NOT_REPLACING_CERTIFICATE); 991e1051a39Sopenharmony_ci goto out; 992e1051a39Sopenharmony_ci } 993e1051a39Sopenharmony_ci 994e1051a39Sopenharmony_ci if (chain != NULL) { 995e1051a39Sopenharmony_ci dup_chain = X509_chain_up_ref(chain); 996e1051a39Sopenharmony_ci if (dup_chain == NULL) { 997e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 998e1051a39Sopenharmony_ci goto out; 999e1051a39Sopenharmony_ci } 1000e1051a39Sopenharmony_ci } 1001e1051a39Sopenharmony_ci 1002e1051a39Sopenharmony_ci sk_X509_pop_free(c->pkeys[i].chain, X509_free); 1003e1051a39Sopenharmony_ci c->pkeys[i].chain = dup_chain; 1004e1051a39Sopenharmony_ci 1005e1051a39Sopenharmony_ci X509_free(c->pkeys[i].x509); 1006e1051a39Sopenharmony_ci X509_up_ref(x509); 1007e1051a39Sopenharmony_ci c->pkeys[i].x509 = x509; 1008e1051a39Sopenharmony_ci 1009e1051a39Sopenharmony_ci EVP_PKEY_free(c->pkeys[i].privatekey); 1010e1051a39Sopenharmony_ci EVP_PKEY_up_ref(privatekey); 1011e1051a39Sopenharmony_ci c->pkeys[i].privatekey = privatekey; 1012e1051a39Sopenharmony_ci 1013e1051a39Sopenharmony_ci c->key = &(c->pkeys[i]); 1014e1051a39Sopenharmony_ci 1015e1051a39Sopenharmony_ci ret = 1; 1016e1051a39Sopenharmony_ci out: 1017e1051a39Sopenharmony_ci EVP_PKEY_free(pubkey); 1018e1051a39Sopenharmony_ci return ret; 1019e1051a39Sopenharmony_ci} 1020e1051a39Sopenharmony_ci 1021e1051a39Sopenharmony_ciint SSL_use_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey, 1022e1051a39Sopenharmony_ci STACK_OF(X509) *chain, int override) 1023e1051a39Sopenharmony_ci{ 1024e1051a39Sopenharmony_ci return ssl_set_cert_and_key(ssl, NULL, x509, privatekey, chain, override); 1025e1051a39Sopenharmony_ci} 1026e1051a39Sopenharmony_ci 1027e1051a39Sopenharmony_ciint SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey, 1028e1051a39Sopenharmony_ci STACK_OF(X509) *chain, int override) 1029e1051a39Sopenharmony_ci{ 1030e1051a39Sopenharmony_ci return ssl_set_cert_and_key(NULL, ctx, x509, privatekey, chain, override); 1031e1051a39Sopenharmony_ci} 1032