1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2016-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 <limits.h> 11e1051a39Sopenharmony_ci#include <string.h> 12e1051a39Sopenharmony_ci 13e1051a39Sopenharmony_ci#include <openssl/ct.h> 14e1051a39Sopenharmony_ci#include <openssl/err.h> 15e1051a39Sopenharmony_ci#include <openssl/evp.h> 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci#include "ct_local.h" 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_ci/* 20e1051a39Sopenharmony_ci * Decodes the base64 string |in| into |out|. 21e1051a39Sopenharmony_ci * A new string will be malloc'd and assigned to |out|. This will be owned by 22e1051a39Sopenharmony_ci * the caller. Do not provide a pre-allocated string in |out|. 23e1051a39Sopenharmony_ci */ 24e1051a39Sopenharmony_cistatic int ct_base64_decode(const char *in, unsigned char **out) 25e1051a39Sopenharmony_ci{ 26e1051a39Sopenharmony_ci size_t inlen = strlen(in); 27e1051a39Sopenharmony_ci int outlen, i; 28e1051a39Sopenharmony_ci unsigned char *outbuf = NULL; 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ci if (inlen == 0) { 31e1051a39Sopenharmony_ci *out = NULL; 32e1051a39Sopenharmony_ci return 0; 33e1051a39Sopenharmony_ci } 34e1051a39Sopenharmony_ci 35e1051a39Sopenharmony_ci outlen = (inlen / 4) * 3; 36e1051a39Sopenharmony_ci outbuf = OPENSSL_malloc(outlen); 37e1051a39Sopenharmony_ci if (outbuf == NULL) { 38e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); 39e1051a39Sopenharmony_ci goto err; 40e1051a39Sopenharmony_ci } 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ci outlen = EVP_DecodeBlock(outbuf, (unsigned char *)in, inlen); 43e1051a39Sopenharmony_ci if (outlen < 0) { 44e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, CT_R_BASE64_DECODE_ERROR); 45e1051a39Sopenharmony_ci goto err; 46e1051a39Sopenharmony_ci } 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci /* Subtract padding bytes from |outlen|. Any more than 2 is malformed. */ 49e1051a39Sopenharmony_ci i = 0; 50e1051a39Sopenharmony_ci while (in[--inlen] == '=') { 51e1051a39Sopenharmony_ci --outlen; 52e1051a39Sopenharmony_ci if (++i > 2) 53e1051a39Sopenharmony_ci goto err; 54e1051a39Sopenharmony_ci } 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci *out = outbuf; 57e1051a39Sopenharmony_ci return outlen; 58e1051a39Sopenharmony_cierr: 59e1051a39Sopenharmony_ci OPENSSL_free(outbuf); 60e1051a39Sopenharmony_ci return -1; 61e1051a39Sopenharmony_ci} 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_ciSCT *SCT_new_from_base64(unsigned char version, const char *logid_base64, 64e1051a39Sopenharmony_ci ct_log_entry_type_t entry_type, uint64_t timestamp, 65e1051a39Sopenharmony_ci const char *extensions_base64, 66e1051a39Sopenharmony_ci const char *signature_base64) 67e1051a39Sopenharmony_ci{ 68e1051a39Sopenharmony_ci SCT *sct = SCT_new(); 69e1051a39Sopenharmony_ci unsigned char *dec = NULL; 70e1051a39Sopenharmony_ci const unsigned char* p = NULL; 71e1051a39Sopenharmony_ci int declen; 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci if (sct == NULL) { 74e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); 75e1051a39Sopenharmony_ci return NULL; 76e1051a39Sopenharmony_ci } 77e1051a39Sopenharmony_ci 78e1051a39Sopenharmony_ci /* 79e1051a39Sopenharmony_ci * RFC6962 section 4.1 says we "MUST NOT expect this to be 0", but we 80e1051a39Sopenharmony_ci * can only construct SCT versions that have been defined. 81e1051a39Sopenharmony_ci */ 82e1051a39Sopenharmony_ci if (!SCT_set_version(sct, version)) { 83e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, CT_R_SCT_UNSUPPORTED_VERSION); 84e1051a39Sopenharmony_ci goto err; 85e1051a39Sopenharmony_ci } 86e1051a39Sopenharmony_ci 87e1051a39Sopenharmony_ci declen = ct_base64_decode(logid_base64, &dec); 88e1051a39Sopenharmony_ci if (declen < 0) { 89e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR); 90e1051a39Sopenharmony_ci goto err; 91e1051a39Sopenharmony_ci } 92e1051a39Sopenharmony_ci if (!SCT_set0_log_id(sct, dec, declen)) 93e1051a39Sopenharmony_ci goto err; 94e1051a39Sopenharmony_ci dec = NULL; 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci declen = ct_base64_decode(extensions_base64, &dec); 97e1051a39Sopenharmony_ci if (declen < 0) { 98e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR); 99e1051a39Sopenharmony_ci goto err; 100e1051a39Sopenharmony_ci } 101e1051a39Sopenharmony_ci SCT_set0_extensions(sct, dec, declen); 102e1051a39Sopenharmony_ci dec = NULL; 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_ci declen = ct_base64_decode(signature_base64, &dec); 105e1051a39Sopenharmony_ci if (declen < 0) { 106e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR); 107e1051a39Sopenharmony_ci goto err; 108e1051a39Sopenharmony_ci } 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ci p = dec; 111e1051a39Sopenharmony_ci if (o2i_SCT_signature(sct, &p, declen) <= 0) 112e1051a39Sopenharmony_ci goto err; 113e1051a39Sopenharmony_ci OPENSSL_free(dec); 114e1051a39Sopenharmony_ci dec = NULL; 115e1051a39Sopenharmony_ci 116e1051a39Sopenharmony_ci SCT_set_timestamp(sct, timestamp); 117e1051a39Sopenharmony_ci 118e1051a39Sopenharmony_ci if (!SCT_set_log_entry_type(sct, entry_type)) 119e1051a39Sopenharmony_ci goto err; 120e1051a39Sopenharmony_ci 121e1051a39Sopenharmony_ci return sct; 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci err: 124e1051a39Sopenharmony_ci OPENSSL_free(dec); 125e1051a39Sopenharmony_ci SCT_free(sct); 126e1051a39Sopenharmony_ci return NULL; 127e1051a39Sopenharmony_ci} 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ci/* 130e1051a39Sopenharmony_ci * Allocate, build and returns a new |ct_log| from input |pkey_base64| 131e1051a39Sopenharmony_ci * It returns 1 on success, 132e1051a39Sopenharmony_ci * 0 on decoding failure, or invalid parameter if any 133e1051a39Sopenharmony_ci * -1 on internal (malloc) failure 134e1051a39Sopenharmony_ci */ 135e1051a39Sopenharmony_ciint CTLOG_new_from_base64_ex(CTLOG **ct_log, const char *pkey_base64, 136e1051a39Sopenharmony_ci const char *name, OSSL_LIB_CTX *libctx, 137e1051a39Sopenharmony_ci const char *propq) 138e1051a39Sopenharmony_ci{ 139e1051a39Sopenharmony_ci unsigned char *pkey_der = NULL; 140e1051a39Sopenharmony_ci int pkey_der_len; 141e1051a39Sopenharmony_ci const unsigned char *p; 142e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_ci if (ct_log == NULL) { 145e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, ERR_R_PASSED_INVALID_ARGUMENT); 146e1051a39Sopenharmony_ci return 0; 147e1051a39Sopenharmony_ci } 148e1051a39Sopenharmony_ci 149e1051a39Sopenharmony_ci pkey_der_len = ct_base64_decode(pkey_base64, &pkey_der); 150e1051a39Sopenharmony_ci if (pkey_der_len < 0) { 151e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID_KEY); 152e1051a39Sopenharmony_ci return 0; 153e1051a39Sopenharmony_ci } 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_ci p = pkey_der; 156e1051a39Sopenharmony_ci pkey = d2i_PUBKEY_ex(NULL, &p, pkey_der_len, libctx, propq); 157e1051a39Sopenharmony_ci OPENSSL_free(pkey_der); 158e1051a39Sopenharmony_ci if (pkey == NULL) { 159e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID_KEY); 160e1051a39Sopenharmony_ci return 0; 161e1051a39Sopenharmony_ci } 162e1051a39Sopenharmony_ci 163e1051a39Sopenharmony_ci *ct_log = CTLOG_new_ex(pkey, name, libctx, propq); 164e1051a39Sopenharmony_ci if (*ct_log == NULL) { 165e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 166e1051a39Sopenharmony_ci return 0; 167e1051a39Sopenharmony_ci } 168e1051a39Sopenharmony_ci 169e1051a39Sopenharmony_ci return 1; 170e1051a39Sopenharmony_ci} 171e1051a39Sopenharmony_ci 172e1051a39Sopenharmony_ciint CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, 173e1051a39Sopenharmony_ci const char *name) 174e1051a39Sopenharmony_ci{ 175e1051a39Sopenharmony_ci return CTLOG_new_from_base64_ex(ct_log, pkey_base64, name, NULL, NULL); 176e1051a39Sopenharmony_ci} 177