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