1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2021 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 <time.h> 12e1051a39Sopenharmony_ci#include <errno.h> 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 15e1051a39Sopenharmony_ci#include <openssl/buffer.h> 16e1051a39Sopenharmony_ci#include <openssl/x509.h> 17e1051a39Sopenharmony_ci#include <openssl/pem.h> 18e1051a39Sopenharmony_ci#include "x509_local.h" 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_cistatic int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, 21e1051a39Sopenharmony_ci long argl, char **ret); 22e1051a39Sopenharmony_cistatic int by_file_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argc, 23e1051a39Sopenharmony_ci long argl, char **ret, OSSL_LIB_CTX *libctx, 24e1051a39Sopenharmony_ci const char *propq); 25e1051a39Sopenharmony_ci 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_cistatic X509_LOOKUP_METHOD x509_file_lookup = { 28e1051a39Sopenharmony_ci "Load file into cache", 29e1051a39Sopenharmony_ci NULL, /* new_item */ 30e1051a39Sopenharmony_ci NULL, /* free */ 31e1051a39Sopenharmony_ci NULL, /* init */ 32e1051a39Sopenharmony_ci NULL, /* shutdown */ 33e1051a39Sopenharmony_ci by_file_ctrl, /* ctrl */ 34e1051a39Sopenharmony_ci NULL, /* get_by_subject */ 35e1051a39Sopenharmony_ci NULL, /* get_by_issuer_serial */ 36e1051a39Sopenharmony_ci NULL, /* get_by_fingerprint */ 37e1051a39Sopenharmony_ci NULL, /* get_by_alias */ 38e1051a39Sopenharmony_ci NULL, /* get_by_subject_ex */ 39e1051a39Sopenharmony_ci by_file_ctrl_ex, /* ctrl_ex */ 40e1051a39Sopenharmony_ci}; 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ciX509_LOOKUP_METHOD *X509_LOOKUP_file(void) 43e1051a39Sopenharmony_ci{ 44e1051a39Sopenharmony_ci return &x509_file_lookup; 45e1051a39Sopenharmony_ci} 46e1051a39Sopenharmony_ci 47e1051a39Sopenharmony_cistatic int by_file_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argp, 48e1051a39Sopenharmony_ci long argl, char **ret, OSSL_LIB_CTX *libctx, 49e1051a39Sopenharmony_ci const char *propq) 50e1051a39Sopenharmony_ci{ 51e1051a39Sopenharmony_ci int ok = 0; 52e1051a39Sopenharmony_ci const char *file; 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_ci switch (cmd) { 55e1051a39Sopenharmony_ci case X509_L_FILE_LOAD: 56e1051a39Sopenharmony_ci if (argl == X509_FILETYPE_DEFAULT) { 57e1051a39Sopenharmony_ci file = ossl_safe_getenv(X509_get_default_cert_file_env()); 58e1051a39Sopenharmony_ci if (file) 59e1051a39Sopenharmony_ci ok = (X509_load_cert_crl_file_ex(ctx, file, X509_FILETYPE_PEM, 60e1051a39Sopenharmony_ci libctx, propq) != 0); 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci else 63e1051a39Sopenharmony_ci ok = (X509_load_cert_crl_file_ex( 64e1051a39Sopenharmony_ci ctx, X509_get_default_cert_file(), 65e1051a39Sopenharmony_ci X509_FILETYPE_PEM, libctx, propq) != 0); 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_ci if (!ok) { 68e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_LOADING_DEFAULTS); 69e1051a39Sopenharmony_ci } 70e1051a39Sopenharmony_ci } else { 71e1051a39Sopenharmony_ci if (argl == X509_FILETYPE_PEM) 72e1051a39Sopenharmony_ci ok = (X509_load_cert_crl_file_ex(ctx, argp, X509_FILETYPE_PEM, 73e1051a39Sopenharmony_ci libctx, propq) != 0); 74e1051a39Sopenharmony_ci else 75e1051a39Sopenharmony_ci ok = (X509_load_cert_file_ex(ctx, argp, (int)argl, libctx, 76e1051a39Sopenharmony_ci propq) != 0); 77e1051a39Sopenharmony_ci } 78e1051a39Sopenharmony_ci break; 79e1051a39Sopenharmony_ci } 80e1051a39Sopenharmony_ci return ok; 81e1051a39Sopenharmony_ci} 82e1051a39Sopenharmony_ci 83e1051a39Sopenharmony_cistatic int by_file_ctrl(X509_LOOKUP *ctx, int cmd, 84e1051a39Sopenharmony_ci const char *argp, long argl, char **ret) 85e1051a39Sopenharmony_ci{ 86e1051a39Sopenharmony_ci return by_file_ctrl_ex(ctx, cmd, argp, argl, ret, NULL, NULL); 87e1051a39Sopenharmony_ci} 88e1051a39Sopenharmony_ci 89e1051a39Sopenharmony_ciint X509_load_cert_file_ex(X509_LOOKUP *ctx, const char *file, int type, 90e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 91e1051a39Sopenharmony_ci{ 92e1051a39Sopenharmony_ci int ret = 0; 93e1051a39Sopenharmony_ci BIO *in = NULL; 94e1051a39Sopenharmony_ci int i, count = 0; 95e1051a39Sopenharmony_ci X509 *x = NULL; 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci in = BIO_new(BIO_s_file()); 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { 100e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB); 101e1051a39Sopenharmony_ci goto err; 102e1051a39Sopenharmony_ci } 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_ci if (type != X509_FILETYPE_PEM && type != X509_FILETYPE_ASN1) { 105e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_BAD_X509_FILETYPE); 106e1051a39Sopenharmony_ci goto err; 107e1051a39Sopenharmony_ci } 108e1051a39Sopenharmony_ci x = X509_new_ex(libctx, propq); 109e1051a39Sopenharmony_ci if (x == NULL) { 110e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 111e1051a39Sopenharmony_ci goto err; 112e1051a39Sopenharmony_ci } 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_ci if (type == X509_FILETYPE_PEM) { 115e1051a39Sopenharmony_ci for (;;) { 116e1051a39Sopenharmony_ci ERR_set_mark(); 117e1051a39Sopenharmony_ci if (PEM_read_bio_X509_AUX(in, &x, NULL, "") == NULL) { 118e1051a39Sopenharmony_ci if ((ERR_GET_REASON(ERR_peek_last_error()) == 119e1051a39Sopenharmony_ci PEM_R_NO_START_LINE) && (count > 0)) { 120e1051a39Sopenharmony_ci ERR_pop_to_mark(); 121e1051a39Sopenharmony_ci break; 122e1051a39Sopenharmony_ci } else { 123e1051a39Sopenharmony_ci ERR_clear_last_mark(); 124e1051a39Sopenharmony_ci goto err; 125e1051a39Sopenharmony_ci } 126e1051a39Sopenharmony_ci } 127e1051a39Sopenharmony_ci ERR_clear_last_mark(); 128e1051a39Sopenharmony_ci i = X509_STORE_add_cert(ctx->store_ctx, x); 129e1051a39Sopenharmony_ci if (!i) 130e1051a39Sopenharmony_ci goto err; 131e1051a39Sopenharmony_ci count++; 132e1051a39Sopenharmony_ci X509_free(x); 133e1051a39Sopenharmony_ci x = NULL; 134e1051a39Sopenharmony_ci } 135e1051a39Sopenharmony_ci ret = count; 136e1051a39Sopenharmony_ci } else if (type == X509_FILETYPE_ASN1) { 137e1051a39Sopenharmony_ci if (d2i_X509_bio(in, &x) == NULL) { 138e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); 139e1051a39Sopenharmony_ci goto err; 140e1051a39Sopenharmony_ci } 141e1051a39Sopenharmony_ci i = X509_STORE_add_cert(ctx->store_ctx, x); 142e1051a39Sopenharmony_ci if (!i) 143e1051a39Sopenharmony_ci goto err; 144e1051a39Sopenharmony_ci ret = i; 145e1051a39Sopenharmony_ci } 146e1051a39Sopenharmony_ci if (ret == 0) 147e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_NO_CERTIFICATE_FOUND); 148e1051a39Sopenharmony_ci err: 149e1051a39Sopenharmony_ci X509_free(x); 150e1051a39Sopenharmony_ci BIO_free(in); 151e1051a39Sopenharmony_ci return ret; 152e1051a39Sopenharmony_ci} 153e1051a39Sopenharmony_ci 154e1051a39Sopenharmony_ciint X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) 155e1051a39Sopenharmony_ci{ 156e1051a39Sopenharmony_ci return X509_load_cert_file_ex(ctx, file, type, NULL, NULL); 157e1051a39Sopenharmony_ci} 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_ciint X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) 160e1051a39Sopenharmony_ci{ 161e1051a39Sopenharmony_ci int ret = 0; 162e1051a39Sopenharmony_ci BIO *in = NULL; 163e1051a39Sopenharmony_ci int i, count = 0; 164e1051a39Sopenharmony_ci X509_CRL *x = NULL; 165e1051a39Sopenharmony_ci 166e1051a39Sopenharmony_ci in = BIO_new(BIO_s_file()); 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_ci if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { 169e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB); 170e1051a39Sopenharmony_ci goto err; 171e1051a39Sopenharmony_ci } 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci if (type == X509_FILETYPE_PEM) { 174e1051a39Sopenharmony_ci for (;;) { 175e1051a39Sopenharmony_ci x = PEM_read_bio_X509_CRL(in, NULL, NULL, ""); 176e1051a39Sopenharmony_ci if (x == NULL) { 177e1051a39Sopenharmony_ci if ((ERR_GET_REASON(ERR_peek_last_error()) == 178e1051a39Sopenharmony_ci PEM_R_NO_START_LINE) && (count > 0)) { 179e1051a39Sopenharmony_ci ERR_clear_error(); 180e1051a39Sopenharmony_ci break; 181e1051a39Sopenharmony_ci } else { 182e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_PEM_LIB); 183e1051a39Sopenharmony_ci goto err; 184e1051a39Sopenharmony_ci } 185e1051a39Sopenharmony_ci } 186e1051a39Sopenharmony_ci i = X509_STORE_add_crl(ctx->store_ctx, x); 187e1051a39Sopenharmony_ci if (!i) 188e1051a39Sopenharmony_ci goto err; 189e1051a39Sopenharmony_ci count++; 190e1051a39Sopenharmony_ci X509_CRL_free(x); 191e1051a39Sopenharmony_ci x = NULL; 192e1051a39Sopenharmony_ci } 193e1051a39Sopenharmony_ci ret = count; 194e1051a39Sopenharmony_ci } else if (type == X509_FILETYPE_ASN1) { 195e1051a39Sopenharmony_ci x = d2i_X509_CRL_bio(in, NULL); 196e1051a39Sopenharmony_ci if (x == NULL) { 197e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); 198e1051a39Sopenharmony_ci goto err; 199e1051a39Sopenharmony_ci } 200e1051a39Sopenharmony_ci i = X509_STORE_add_crl(ctx->store_ctx, x); 201e1051a39Sopenharmony_ci if (!i) 202e1051a39Sopenharmony_ci goto err; 203e1051a39Sopenharmony_ci ret = i; 204e1051a39Sopenharmony_ci } else { 205e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_BAD_X509_FILETYPE); 206e1051a39Sopenharmony_ci goto err; 207e1051a39Sopenharmony_ci } 208e1051a39Sopenharmony_ci if (ret == 0) 209e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_NO_CRL_FOUND); 210e1051a39Sopenharmony_ci err: 211e1051a39Sopenharmony_ci X509_CRL_free(x); 212e1051a39Sopenharmony_ci BIO_free(in); 213e1051a39Sopenharmony_ci return ret; 214e1051a39Sopenharmony_ci} 215e1051a39Sopenharmony_ci 216e1051a39Sopenharmony_ciint X509_load_cert_crl_file_ex(X509_LOOKUP *ctx, const char *file, int type, 217e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 218e1051a39Sopenharmony_ci{ 219e1051a39Sopenharmony_ci STACK_OF(X509_INFO) *inf; 220e1051a39Sopenharmony_ci X509_INFO *itmp; 221e1051a39Sopenharmony_ci BIO *in; 222e1051a39Sopenharmony_ci int i, count = 0; 223e1051a39Sopenharmony_ci 224e1051a39Sopenharmony_ci if (type != X509_FILETYPE_PEM) 225e1051a39Sopenharmony_ci return X509_load_cert_file_ex(ctx, file, type, libctx, propq); 226e1051a39Sopenharmony_ci in = BIO_new_file(file, "r"); 227e1051a39Sopenharmony_ci if (!in) { 228e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB); 229e1051a39Sopenharmony_ci return 0; 230e1051a39Sopenharmony_ci } 231e1051a39Sopenharmony_ci inf = PEM_X509_INFO_read_bio_ex(in, NULL, NULL, "", libctx, propq); 232e1051a39Sopenharmony_ci BIO_free(in); 233e1051a39Sopenharmony_ci if (!inf) { 234e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_PEM_LIB); 235e1051a39Sopenharmony_ci return 0; 236e1051a39Sopenharmony_ci } 237e1051a39Sopenharmony_ci for (i = 0; i < sk_X509_INFO_num(inf); i++) { 238e1051a39Sopenharmony_ci itmp = sk_X509_INFO_value(inf, i); 239e1051a39Sopenharmony_ci if (itmp->x509) { 240e1051a39Sopenharmony_ci if (!X509_STORE_add_cert(ctx->store_ctx, itmp->x509)) 241e1051a39Sopenharmony_ci goto err; 242e1051a39Sopenharmony_ci count++; 243e1051a39Sopenharmony_ci } 244e1051a39Sopenharmony_ci if (itmp->crl) { 245e1051a39Sopenharmony_ci if (!X509_STORE_add_crl(ctx->store_ctx, itmp->crl)) 246e1051a39Sopenharmony_ci goto err; 247e1051a39Sopenharmony_ci count++; 248e1051a39Sopenharmony_ci } 249e1051a39Sopenharmony_ci } 250e1051a39Sopenharmony_ci if (count == 0) 251e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_NO_CERTIFICATE_OR_CRL_FOUND); 252e1051a39Sopenharmony_ci err: 253e1051a39Sopenharmony_ci sk_X509_INFO_pop_free(inf, X509_INFO_free); 254e1051a39Sopenharmony_ci return count; 255e1051a39Sopenharmony_ci} 256e1051a39Sopenharmony_ci 257e1051a39Sopenharmony_ciint X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) 258e1051a39Sopenharmony_ci{ 259e1051a39Sopenharmony_ci return X509_load_cert_crl_file_ex(ctx, file, type, NULL, NULL); 260e1051a39Sopenharmony_ci} 261e1051a39Sopenharmony_ci 262