diff options
Diffstat (limited to 'src/lib/libcrypto')
| -rw-r--r-- | src/lib/libcrypto/ct/ct.h | 0 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/ct_b64.c | 168 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/ct_err.c | 96 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/ct_local.h | 216 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/ct_log.c | 306 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/ct_oct.c | 407 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/ct_policy.c | 98 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/ct_prn.c | 127 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/ct_sct.c | 396 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/ct_sct_ctx.c | 263 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/ct_vfy.c | 140 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/ct_x509v3.c | 104 | ||||
| -rw-r--r-- | src/lib/libcrypto/ct/cterr.h | 0 | 
13 files changed, 2321 insertions, 0 deletions
| diff --git a/src/lib/libcrypto/ct/ct.h b/src/lib/libcrypto/ct/ct.h new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/src/lib/libcrypto/ct/ct.h | |||
| diff --git a/src/lib/libcrypto/ct/ct_b64.c b/src/lib/libcrypto/ct/ct_b64.c new file mode 100644 index 0000000000..4abe11ca29 --- /dev/null +++ b/src/lib/libcrypto/ct/ct_b64.c | |||
| @@ -0,0 +1,168 @@ | |||
| 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 | } | ||
| diff --git a/src/lib/libcrypto/ct/ct_err.c b/src/lib/libcrypto/ct/ct_err.c new file mode 100644 index 0000000000..c0c62fee6c --- /dev/null +++ b/src/lib/libcrypto/ct/ct_err.c | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | /* | ||
| 2 | * Generated by util/mkerr.pl DO NOT EDIT | ||
| 3 | * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. | ||
| 4 | * | ||
| 5 | * Licensed under the OpenSSL license (the "License"). You may not use | ||
| 6 | * this file except in compliance with the License. You can obtain a copy | ||
| 7 | * in the file LICENSE in the source distribution or at | ||
| 8 | * https://www.openssl.org/source/license.html | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <openssl/err.h> | ||
| 12 | #include <openssl/cterr.h> | ||
| 13 | |||
| 14 | #ifndef OPENSSL_NO_ERR | ||
| 15 | |||
| 16 | static const ERR_STRING_DATA CT_str_functs[] = { | ||
| 17 | {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW, 0), "CTLOG_new"}, | ||
| 18 | {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW_FROM_BASE64, 0), | ||
| 19 | "CTLOG_new_from_base64"}, | ||
| 20 | {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW_FROM_CONF, 0), "ctlog_new_from_conf"}, | ||
| 21 | {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_CTX_NEW, 0), | ||
| 22 | "ctlog_store_load_ctx_new"}, | ||
| 23 | {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_FILE, 0), | ||
| 24 | "CTLOG_STORE_load_file"}, | ||
| 25 | {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_LOG, 0), | ||
| 26 | "ctlog_store_load_log"}, | ||
| 27 | {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_NEW, 0), "CTLOG_STORE_new"}, | ||
| 28 | {ERR_PACK(ERR_LIB_CT, CT_F_CT_BASE64_DECODE, 0), "ct_base64_decode"}, | ||
| 29 | {ERR_PACK(ERR_LIB_CT, CT_F_CT_POLICY_EVAL_CTX_NEW, 0), | ||
| 30 | "CT_POLICY_EVAL_CTX_new"}, | ||
| 31 | {ERR_PACK(ERR_LIB_CT, CT_F_CT_V1_LOG_ID_FROM_PKEY, 0), | ||
| 32 | "ct_v1_log_id_from_pkey"}, | ||
| 33 | {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT, 0), "i2o_SCT"}, | ||
| 34 | {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT_LIST, 0), "i2o_SCT_LIST"}, | ||
| 35 | {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT_SIGNATURE, 0), "i2o_SCT_signature"}, | ||
| 36 | {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT, 0), "o2i_SCT"}, | ||
| 37 | {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT_LIST, 0), "o2i_SCT_LIST"}, | ||
| 38 | {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT_SIGNATURE, 0), "o2i_SCT_signature"}, | ||
| 39 | {ERR_PACK(ERR_LIB_CT, CT_F_SCT_CTX_NEW, 0), "SCT_CTX_new"}, | ||
| 40 | {ERR_PACK(ERR_LIB_CT, CT_F_SCT_CTX_VERIFY, 0), "SCT_CTX_verify"}, | ||
| 41 | {ERR_PACK(ERR_LIB_CT, CT_F_SCT_NEW, 0), "SCT_new"}, | ||
| 42 | {ERR_PACK(ERR_LIB_CT, CT_F_SCT_NEW_FROM_BASE64, 0), "SCT_new_from_base64"}, | ||
| 43 | {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET0_LOG_ID, 0), "SCT_set0_log_id"}, | ||
| 44 | {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_EXTENSIONS, 0), "SCT_set1_extensions"}, | ||
| 45 | {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_LOG_ID, 0), "SCT_set1_log_id"}, | ||
| 46 | {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_SIGNATURE, 0), "SCT_set1_signature"}, | ||
| 47 | {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_LOG_ENTRY_TYPE, 0), | ||
| 48 | "SCT_set_log_entry_type"}, | ||
| 49 | {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_SIGNATURE_NID, 0), | ||
| 50 | "SCT_set_signature_nid"}, | ||
| 51 | {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_VERSION, 0), "SCT_set_version"}, | ||
| 52 | {0, NULL} | ||
| 53 | }; | ||
| 54 | |||
| 55 | static const ERR_STRING_DATA CT_str_reasons[] = { | ||
| 56 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_BASE64_DECODE_ERROR), "base64 decode error"}, | ||
| 57 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_INVALID_LOG_ID_LENGTH), | ||
| 58 | "invalid log id length"}, | ||
| 59 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_INVALID), "log conf invalid"}, | ||
| 60 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_INVALID_KEY), | ||
| 61 | "log conf invalid key"}, | ||
| 62 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_MISSING_DESCRIPTION), | ||
| 63 | "log conf missing description"}, | ||
| 64 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_MISSING_KEY), | ||
| 65 | "log conf missing key"}, | ||
| 66 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_KEY_INVALID), "log key invalid"}, | ||
| 67 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_FUTURE_TIMESTAMP), | ||
| 68 | "sct future timestamp"}, | ||
| 69 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_INVALID), "sct invalid"}, | ||
| 70 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_INVALID_SIGNATURE), | ||
| 71 | "sct invalid signature"}, | ||
| 72 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_LIST_INVALID), "sct list invalid"}, | ||
| 73 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_LOG_ID_MISMATCH), "sct log id mismatch"}, | ||
| 74 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_NOT_SET), "sct not set"}, | ||
| 75 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_UNSUPPORTED_VERSION), | ||
| 76 | "sct unsupported version"}, | ||
| 77 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_UNRECOGNIZED_SIGNATURE_NID), | ||
| 78 | "unrecognized signature nid"}, | ||
| 79 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_UNSUPPORTED_ENTRY_TYPE), | ||
| 80 | "unsupported entry type"}, | ||
| 81 | {ERR_PACK(ERR_LIB_CT, 0, CT_R_UNSUPPORTED_VERSION), "unsupported version"}, | ||
| 82 | {0, NULL} | ||
| 83 | }; | ||
| 84 | |||
| 85 | #endif | ||
| 86 | |||
| 87 | int ERR_load_CT_strings(void) | ||
| 88 | { | ||
| 89 | #ifndef OPENSSL_NO_ERR | ||
| 90 | if (ERR_func_error_string(CT_str_functs[0].error) == NULL) { | ||
| 91 | ERR_load_strings_const(CT_str_functs); | ||
| 92 | ERR_load_strings_const(CT_str_reasons); | ||
| 93 | } | ||
| 94 | #endif | ||
| 95 | return 1; | ||
| 96 | } | ||
| diff --git a/src/lib/libcrypto/ct/ct_local.h b/src/lib/libcrypto/ct/ct_local.h new file mode 100644 index 0000000000..9f983c91be --- /dev/null +++ b/src/lib/libcrypto/ct/ct_local.h | |||
| @@ -0,0 +1,216 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2015-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 <stddef.h> | ||
| 11 | #include <openssl/ct.h> | ||
| 12 | #include <openssl/evp.h> | ||
| 13 | #include <openssl/x509.h> | ||
| 14 | #include <openssl/x509v3.h> | ||
| 15 | #include <openssl/safestack.h> | ||
| 16 | |||
| 17 | /* | ||
| 18 | * From RFC6962: opaque SerializedSCT<1..2^16-1>; struct { SerializedSCT | ||
| 19 | * sct_list <1..2^16-1>; } SignedCertificateTimestampList; | ||
| 20 | */ | ||
| 21 | # define MAX_SCT_SIZE 65535 | ||
| 22 | # define MAX_SCT_LIST_SIZE MAX_SCT_SIZE | ||
| 23 | |||
| 24 | /* | ||
| 25 | * Macros to read and write integers in network-byte order. | ||
| 26 | */ | ||
| 27 | |||
| 28 | #define n2s(c,s) ((s=(((unsigned int)((c)[0]))<< 8)| \ | ||
| 29 | (((unsigned int)((c)[1])) )),c+=2) | ||
| 30 | |||
| 31 | #define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \ | ||
| 32 | c[1]=(unsigned char)(((s) )&0xff)),c+=2) | ||
| 33 | |||
| 34 | #define l2n3(l,c) ((c[0]=(unsigned char)(((l)>>16)&0xff), \ | ||
| 35 | c[1]=(unsigned char)(((l)>> 8)&0xff), \ | ||
| 36 | c[2]=(unsigned char)(((l) )&0xff)),c+=3) | ||
| 37 | |||
| 38 | #define n2l8(c,l) (l =((uint64_t)(*((c)++)))<<56, \ | ||
| 39 | l|=((uint64_t)(*((c)++)))<<48, \ | ||
| 40 | l|=((uint64_t)(*((c)++)))<<40, \ | ||
| 41 | l|=((uint64_t)(*((c)++)))<<32, \ | ||
| 42 | l|=((uint64_t)(*((c)++)))<<24, \ | ||
| 43 | l|=((uint64_t)(*((c)++)))<<16, \ | ||
| 44 | l|=((uint64_t)(*((c)++)))<< 8, \ | ||
| 45 | l|=((uint64_t)(*((c)++)))) | ||
| 46 | |||
| 47 | #define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \ | ||
| 48 | *((c)++)=(unsigned char)(((l)>>48)&0xff), \ | ||
| 49 | *((c)++)=(unsigned char)(((l)>>40)&0xff), \ | ||
| 50 | *((c)++)=(unsigned char)(((l)>>32)&0xff), \ | ||
| 51 | *((c)++)=(unsigned char)(((l)>>24)&0xff), \ | ||
| 52 | *((c)++)=(unsigned char)(((l)>>16)&0xff), \ | ||
| 53 | *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ | ||
| 54 | *((c)++)=(unsigned char)(((l) )&0xff)) | ||
| 55 | |||
| 56 | /* Signed Certificate Timestamp */ | ||
| 57 | struct sct_st { | ||
| 58 | sct_version_t version; | ||
| 59 | /* If version is not SCT_VERSION_V1, this contains the encoded SCT */ | ||
| 60 | unsigned char *sct; | ||
| 61 | size_t sct_len; | ||
| 62 | /* If version is SCT_VERSION_V1, fields below contain components of the SCT */ | ||
| 63 | unsigned char *log_id; | ||
| 64 | size_t log_id_len; | ||
| 65 | /* | ||
| 66 | * Note, we cannot distinguish between an unset timestamp, and one | ||
| 67 | * that is set to 0. However since CT didn't exist in 1970, no real | ||
| 68 | * SCT should ever be set as such. | ||
| 69 | */ | ||
| 70 | uint64_t timestamp; | ||
| 71 | unsigned char *ext; | ||
| 72 | size_t ext_len; | ||
| 73 | unsigned char hash_alg; | ||
| 74 | unsigned char sig_alg; | ||
| 75 | unsigned char *sig; | ||
| 76 | size_t sig_len; | ||
| 77 | /* Log entry type */ | ||
| 78 | ct_log_entry_type_t entry_type; | ||
| 79 | /* Where this SCT was found, e.g. certificate, OCSP response, etc. */ | ||
| 80 | sct_source_t source; | ||
| 81 | /* The result of the last attempt to validate this SCT. */ | ||
| 82 | sct_validation_status_t validation_status; | ||
| 83 | }; | ||
| 84 | |||
| 85 | /* Miscellaneous data that is useful when verifying an SCT */ | ||
| 86 | struct sct_ctx_st { | ||
| 87 | /* Public key */ | ||
| 88 | EVP_PKEY *pkey; | ||
| 89 | /* Hash of public key */ | ||
| 90 | unsigned char *pkeyhash; | ||
| 91 | size_t pkeyhashlen; | ||
| 92 | /* For pre-certificate: issuer public key hash */ | ||
| 93 | unsigned char *ihash; | ||
| 94 | size_t ihashlen; | ||
| 95 | /* certificate encoding */ | ||
| 96 | unsigned char *certder; | ||
| 97 | size_t certderlen; | ||
| 98 | /* pre-certificate encoding */ | ||
| 99 | unsigned char *preder; | ||
| 100 | size_t prederlen; | ||
| 101 | /* milliseconds since epoch (to check that the SCT isn't from the future) */ | ||
| 102 | uint64_t epoch_time_in_ms; | ||
| 103 | }; | ||
| 104 | |||
| 105 | /* Context when evaluating whether a Certificate Transparency policy is met */ | ||
| 106 | struct ct_policy_eval_ctx_st { | ||
| 107 | X509 *cert; | ||
| 108 | X509 *issuer; | ||
| 109 | CTLOG_STORE *log_store; | ||
| 110 | /* milliseconds since epoch (to check that SCTs aren't from the future) */ | ||
| 111 | uint64_t epoch_time_in_ms; | ||
| 112 | }; | ||
| 113 | |||
| 114 | /* | ||
| 115 | * Creates a new context for verifying an SCT. | ||
| 116 | */ | ||
| 117 | SCT_CTX *SCT_CTX_new(void); | ||
| 118 | /* | ||
| 119 | * Deletes an SCT verification context. | ||
| 120 | */ | ||
| 121 | void SCT_CTX_free(SCT_CTX *sctx); | ||
| 122 | |||
| 123 | /* | ||
| 124 | * Sets the certificate that the SCT was created for. | ||
| 125 | * If *cert does not have a poison extension, presigner must be NULL. | ||
| 126 | * If *cert does not have a poison extension, it may have a single SCT | ||
| 127 | * (NID_ct_precert_scts) extension. | ||
| 128 | * If either *cert or *presigner have an AKID (NID_authority_key_identifier) | ||
| 129 | * extension, both must have one. | ||
| 130 | * Returns 1 on success, 0 on failure. | ||
| 131 | */ | ||
| 132 | __owur int SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner); | ||
| 133 | |||
| 134 | /* | ||
| 135 | * Sets the issuer of the certificate that the SCT was created for. | ||
| 136 | * This is just a convenience method to save extracting the public key and | ||
| 137 | * calling SCT_CTX_set1_issuer_pubkey(). | ||
| 138 | * Issuer must not be NULL. | ||
| 139 | * Returns 1 on success, 0 on failure. | ||
| 140 | */ | ||
| 141 | __owur int SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer); | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Sets the public key of the issuer of the certificate that the SCT was created | ||
| 145 | * for. | ||
| 146 | * The public key must not be NULL. | ||
| 147 | * Returns 1 on success, 0 on failure. | ||
| 148 | */ | ||
| 149 | __owur int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey); | ||
| 150 | |||
| 151 | /* | ||
| 152 | * Sets the public key of the CT log that the SCT is from. | ||
| 153 | * Returns 1 on success, 0 on failure. | ||
| 154 | */ | ||
| 155 | __owur int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey); | ||
| 156 | |||
| 157 | /* | ||
| 158 | * Sets the time to evaluate the SCT against, in milliseconds since the Unix | ||
| 159 | * epoch. If the SCT's timestamp is after this time, it will be interpreted as | ||
| 160 | * having been issued in the future. RFC6962 states that "TLS clients MUST | ||
| 161 | * reject SCTs whose timestamp is in the future", so an SCT will not validate | ||
| 162 | * in this case. | ||
| 163 | */ | ||
| 164 | void SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms); | ||
| 165 | |||
| 166 | /* | ||
| 167 | * Verifies an SCT with the given context. | ||
| 168 | * Returns 1 if the SCT verifies successfully; any other value indicates | ||
| 169 | * failure. See EVP_DigestVerifyFinal() for the meaning of those values. | ||
| 170 | */ | ||
| 171 | __owur int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct); | ||
| 172 | |||
| 173 | /* | ||
| 174 | * Does this SCT have the minimum fields populated to be usable? | ||
| 175 | * Returns 1 if so, 0 otherwise. | ||
| 176 | */ | ||
| 177 | __owur int SCT_is_complete(const SCT *sct); | ||
| 178 | |||
| 179 | /* | ||
| 180 | * Does this SCT have the signature-related fields populated? | ||
| 181 | * Returns 1 if so, 0 otherwise. | ||
| 182 | * This checks that the signature and hash algorithms are set to supported | ||
| 183 | * values and that the signature field is set. | ||
| 184 | */ | ||
| 185 | __owur int SCT_signature_is_complete(const SCT *sct); | ||
| 186 | |||
| 187 | /* | ||
| 188 | * TODO(RJPercival): Create an SCT_signature struct and make i2o_SCT_signature | ||
| 189 | * and o2i_SCT_signature conform to the i2d/d2i conventions. | ||
| 190 | */ | ||
| 191 | |||
| 192 | /* | ||
| 193 | * Serialize (to TLS format) an |sct| signature and write it to |out|. | ||
| 194 | * If |out| is null, no signature will be output but the length will be returned. | ||
| 195 | * If |out| points to a null pointer, a string will be allocated to hold the | ||
| 196 | * TLS-format signature. It is the responsibility of the caller to free it. | ||
| 197 | * If |out| points to an allocated string, the signature will be written to it. | ||
| 198 | * The length of the signature in TLS format will be returned. | ||
| 199 | */ | ||
| 200 | __owur int i2o_SCT_signature(const SCT *sct, unsigned char **out); | ||
| 201 | |||
| 202 | /* | ||
| 203 | * Parses an SCT signature in TLS format and populates the |sct| with it. | ||
| 204 | * |in| should be a pointer to a string containing the TLS-format signature. | ||
| 205 | * |in| will be advanced to the end of the signature if parsing succeeds. | ||
| 206 | * |len| should be the length of the signature in |in|. | ||
| 207 | * Returns the number of bytes parsed, or a negative integer if an error occurs. | ||
| 208 | * If an error occurs, the SCT's signature NID may be updated whilst the | ||
| 209 | * signature field itself remains unset. | ||
| 210 | */ | ||
| 211 | __owur int o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len); | ||
| 212 | |||
| 213 | /* | ||
| 214 | * Handlers for Certificate Transparency X509v3/OCSP extensions | ||
| 215 | */ | ||
| 216 | extern const X509V3_EXT_METHOD v3_ct_scts[3]; | ||
| diff --git a/src/lib/libcrypto/ct/ct_log.c b/src/lib/libcrypto/ct/ct_log.c new file mode 100644 index 0000000000..c1bca3e141 --- /dev/null +++ b/src/lib/libcrypto/ct/ct_log.c | |||
| @@ -0,0 +1,306 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2016-2018 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 <stdlib.h> | ||
| 11 | #include <string.h> | ||
| 12 | |||
| 13 | #include <openssl/conf.h> | ||
| 14 | #include <openssl/ct.h> | ||
| 15 | #include <openssl/err.h> | ||
| 16 | #include <openssl/evp.h> | ||
| 17 | #include <openssl/safestack.h> | ||
| 18 | |||
| 19 | #include "internal/cryptlib.h" | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Information about a CT log server. | ||
| 23 | */ | ||
| 24 | struct ctlog_st { | ||
| 25 | char *name; | ||
| 26 | uint8_t log_id[CT_V1_HASHLEN]; | ||
| 27 | EVP_PKEY *public_key; | ||
| 28 | }; | ||
| 29 | |||
| 30 | /* | ||
| 31 | * A store for multiple CTLOG instances. | ||
| 32 | * It takes ownership of any CTLOG instances added to it. | ||
| 33 | */ | ||
| 34 | struct ctlog_store_st { | ||
| 35 | STACK_OF(CTLOG) *logs; | ||
| 36 | }; | ||
| 37 | |||
| 38 | /* The context when loading a CT log list from a CONF file. */ | ||
| 39 | typedef struct ctlog_store_load_ctx_st { | ||
| 40 | CTLOG_STORE *log_store; | ||
| 41 | CONF *conf; | ||
| 42 | size_t invalid_log_entries; | ||
| 43 | } CTLOG_STORE_LOAD_CTX; | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Creates an empty context for loading a CT log store. | ||
| 47 | * It should be populated before use. | ||
| 48 | */ | ||
| 49 | static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void); | ||
| 50 | |||
| 51 | /* | ||
| 52 | * Deletes a CT log store load context. | ||
| 53 | * Does not delete any of the fields. | ||
| 54 | */ | ||
| 55 | static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* ctx); | ||
| 56 | |||
| 57 | static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void) | ||
| 58 | { | ||
| 59 | CTLOG_STORE_LOAD_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); | ||
| 60 | |||
| 61 | if (ctx == NULL) | ||
| 62 | CTerr(CT_F_CTLOG_STORE_LOAD_CTX_NEW, ERR_R_MALLOC_FAILURE); | ||
| 63 | |||
| 64 | return ctx; | ||
| 65 | } | ||
| 66 | |||
| 67 | static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* ctx) | ||
| 68 | { | ||
| 69 | OPENSSL_free(ctx); | ||
| 70 | } | ||
| 71 | |||
| 72 | /* Converts a log's public key into a SHA256 log ID */ | ||
| 73 | static int ct_v1_log_id_from_pkey(EVP_PKEY *pkey, | ||
| 74 | unsigned char log_id[CT_V1_HASHLEN]) | ||
| 75 | { | ||
| 76 | int ret = 0; | ||
| 77 | unsigned char *pkey_der = NULL; | ||
| 78 | int pkey_der_len = i2d_PUBKEY(pkey, &pkey_der); | ||
| 79 | |||
| 80 | if (pkey_der_len <= 0) { | ||
| 81 | CTerr(CT_F_CT_V1_LOG_ID_FROM_PKEY, CT_R_LOG_KEY_INVALID); | ||
| 82 | goto err; | ||
| 83 | } | ||
| 84 | |||
| 85 | SHA256(pkey_der, pkey_der_len, log_id); | ||
| 86 | ret = 1; | ||
| 87 | err: | ||
| 88 | OPENSSL_free(pkey_der); | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 92 | CTLOG_STORE *CTLOG_STORE_new(void) | ||
| 93 | { | ||
| 94 | CTLOG_STORE *ret = OPENSSL_zalloc(sizeof(*ret)); | ||
| 95 | |||
| 96 | if (ret == NULL) { | ||
| 97 | CTerr(CT_F_CTLOG_STORE_NEW, ERR_R_MALLOC_FAILURE); | ||
| 98 | return NULL; | ||
| 99 | } | ||
| 100 | |||
| 101 | ret->logs = sk_CTLOG_new_null(); | ||
| 102 | if (ret->logs == NULL) | ||
| 103 | goto err; | ||
| 104 | |||
| 105 | return ret; | ||
| 106 | err: | ||
| 107 | OPENSSL_free(ret); | ||
| 108 | return NULL; | ||
| 109 | } | ||
| 110 | |||
| 111 | void CTLOG_STORE_free(CTLOG_STORE *store) | ||
| 112 | { | ||
| 113 | if (store != NULL) { | ||
| 114 | sk_CTLOG_pop_free(store->logs, CTLOG_free); | ||
| 115 | OPENSSL_free(store); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | static int ctlog_new_from_conf(CTLOG **ct_log, const CONF *conf, const char *section) | ||
| 120 | { | ||
| 121 | const char *description = NCONF_get_string(conf, section, "description"); | ||
| 122 | char *pkey_base64; | ||
| 123 | |||
| 124 | if (description == NULL) { | ||
| 125 | CTerr(CT_F_CTLOG_NEW_FROM_CONF, CT_R_LOG_CONF_MISSING_DESCRIPTION); | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | pkey_base64 = NCONF_get_string(conf, section, "key"); | ||
| 130 | if (pkey_base64 == NULL) { | ||
| 131 | CTerr(CT_F_CTLOG_NEW_FROM_CONF, CT_R_LOG_CONF_MISSING_KEY); | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | return CTLOG_new_from_base64(ct_log, pkey_base64, description); | ||
| 136 | } | ||
| 137 | |||
| 138 | int CTLOG_STORE_load_default_file(CTLOG_STORE *store) | ||
| 139 | { | ||
| 140 | const char *fpath = ossl_safe_getenv(CTLOG_FILE_EVP); | ||
| 141 | |||
| 142 | if (fpath == NULL) | ||
| 143 | fpath = CTLOG_FILE; | ||
| 144 | |||
| 145 | return CTLOG_STORE_load_file(store, fpath); | ||
| 146 | } | ||
| 147 | |||
| 148 | /* | ||
| 149 | * Called by CONF_parse_list, which stops if this returns <= 0, | ||
| 150 | * Otherwise, one bad log entry would stop loading of any of | ||
| 151 | * the following log entries. | ||
| 152 | * It may stop parsing and returns -1 on any internal (malloc) error. | ||
| 153 | */ | ||
| 154 | static int ctlog_store_load_log(const char *log_name, int log_name_len, | ||
| 155 | void *arg) | ||
| 156 | { | ||
| 157 | CTLOG_STORE_LOAD_CTX *load_ctx = arg; | ||
| 158 | CTLOG *ct_log = NULL; | ||
| 159 | /* log_name may not be null-terminated, so fix that before using it */ | ||
| 160 | char *tmp; | ||
| 161 | int ret = 0; | ||
| 162 | |||
| 163 | /* log_name will be NULL for empty list entries */ | ||
| 164 | if (log_name == NULL) | ||
| 165 | return 1; | ||
| 166 | |||
| 167 | tmp = OPENSSL_strndup(log_name, log_name_len); | ||
| 168 | if (tmp == NULL) | ||
| 169 | goto mem_err; | ||
| 170 | |||
| 171 | ret = ctlog_new_from_conf(&ct_log, load_ctx->conf, tmp); | ||
| 172 | OPENSSL_free(tmp); | ||
| 173 | |||
| 174 | if (ret < 0) { | ||
| 175 | /* Propagate any internal error */ | ||
| 176 | return ret; | ||
| 177 | } | ||
| 178 | if (ret == 0) { | ||
| 179 | /* If we can't load this log, record that fact and skip it */ | ||
| 180 | ++load_ctx->invalid_log_entries; | ||
| 181 | return 1; | ||
| 182 | } | ||
| 183 | |||
| 184 | if (!sk_CTLOG_push(load_ctx->log_store->logs, ct_log)) { | ||
| 185 | goto mem_err; | ||
| 186 | } | ||
| 187 | return 1; | ||
| 188 | |||
| 189 | mem_err: | ||
| 190 | CTLOG_free(ct_log); | ||
| 191 | CTerr(CT_F_CTLOG_STORE_LOAD_LOG, ERR_R_MALLOC_FAILURE); | ||
| 192 | return -1; | ||
| 193 | } | ||
| 194 | |||
| 195 | int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file) | ||
| 196 | { | ||
| 197 | int ret = 0; | ||
| 198 | char *enabled_logs; | ||
| 199 | CTLOG_STORE_LOAD_CTX* load_ctx = ctlog_store_load_ctx_new(); | ||
| 200 | |||
| 201 | if (load_ctx == NULL) | ||
| 202 | return 0; | ||
| 203 | load_ctx->log_store = store; | ||
| 204 | load_ctx->conf = NCONF_new(NULL); | ||
| 205 | if (load_ctx->conf == NULL) | ||
| 206 | goto end; | ||
| 207 | |||
| 208 | if (NCONF_load(load_ctx->conf, file, NULL) <= 0) { | ||
| 209 | CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID); | ||
| 210 | goto end; | ||
| 211 | } | ||
| 212 | |||
| 213 | enabled_logs = NCONF_get_string(load_ctx->conf, NULL, "enabled_logs"); | ||
| 214 | if (enabled_logs == NULL) { | ||
| 215 | CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID); | ||
| 216 | goto end; | ||
| 217 | } | ||
| 218 | |||
| 219 | if (!CONF_parse_list(enabled_logs, ',', 1, ctlog_store_load_log, load_ctx) || | ||
| 220 | load_ctx->invalid_log_entries > 0) { | ||
| 221 | CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID); | ||
| 222 | goto end; | ||
| 223 | } | ||
| 224 | |||
| 225 | ret = 1; | ||
| 226 | end: | ||
| 227 | NCONF_free(load_ctx->conf); | ||
| 228 | ctlog_store_load_ctx_free(load_ctx); | ||
| 229 | return ret; | ||
| 230 | } | ||
| 231 | |||
| 232 | /* | ||
| 233 | * Initialize a new CTLOG object. | ||
| 234 | * Takes ownership of the public key. | ||
| 235 | * Copies the name. | ||
| 236 | */ | ||
| 237 | CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name) | ||
| 238 | { | ||
| 239 | CTLOG *ret = OPENSSL_zalloc(sizeof(*ret)); | ||
| 240 | |||
| 241 | if (ret == NULL) { | ||
| 242 | CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE); | ||
| 243 | return NULL; | ||
| 244 | } | ||
| 245 | |||
| 246 | ret->name = OPENSSL_strdup(name); | ||
| 247 | if (ret->name == NULL) { | ||
| 248 | CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE); | ||
| 249 | goto err; | ||
| 250 | } | ||
| 251 | |||
| 252 | if (ct_v1_log_id_from_pkey(public_key, ret->log_id) != 1) | ||
| 253 | goto err; | ||
| 254 | |||
| 255 | ret->public_key = public_key; | ||
| 256 | return ret; | ||
| 257 | err: | ||
| 258 | CTLOG_free(ret); | ||
| 259 | return NULL; | ||
| 260 | } | ||
| 261 | |||
| 262 | /* Frees CT log and associated structures */ | ||
| 263 | void CTLOG_free(CTLOG *log) | ||
| 264 | { | ||
| 265 | if (log != NULL) { | ||
| 266 | OPENSSL_free(log->name); | ||
| 267 | EVP_PKEY_free(log->public_key); | ||
| 268 | OPENSSL_free(log); | ||
| 269 | } | ||
| 270 | } | ||
| 271 | |||
| 272 | const char *CTLOG_get0_name(const CTLOG *log) | ||
| 273 | { | ||
| 274 | return log->name; | ||
| 275 | } | ||
| 276 | |||
| 277 | void CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id, | ||
| 278 | size_t *log_id_len) | ||
| 279 | { | ||
| 280 | *log_id = log->log_id; | ||
| 281 | *log_id_len = CT_V1_HASHLEN; | ||
| 282 | } | ||
| 283 | |||
| 284 | EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log) | ||
| 285 | { | ||
| 286 | return log->public_key; | ||
| 287 | } | ||
| 288 | |||
| 289 | /* | ||
| 290 | * Given a log ID, finds the matching log. | ||
| 291 | * Returns NULL if no match found. | ||
| 292 | */ | ||
| 293 | const CTLOG *CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store, | ||
| 294 | const uint8_t *log_id, | ||
| 295 | size_t log_id_len) | ||
| 296 | { | ||
| 297 | int i; | ||
| 298 | |||
| 299 | for (i = 0; i < sk_CTLOG_num(store->logs); ++i) { | ||
| 300 | const CTLOG *log = sk_CTLOG_value(store->logs, i); | ||
| 301 | if (memcmp(log->log_id, log_id, log_id_len) == 0) | ||
| 302 | return log; | ||
| 303 | } | ||
| 304 | |||
| 305 | return NULL; | ||
| 306 | } | ||
| diff --git a/src/lib/libcrypto/ct/ct_oct.c b/src/lib/libcrypto/ct/ct_oct.c new file mode 100644 index 0000000000..d4b6645af4 --- /dev/null +++ b/src/lib/libcrypto/ct/ct_oct.c | |||
| @@ -0,0 +1,407 @@ | |||
| 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 | #ifdef OPENSSL_NO_CT | ||
| 11 | # error "CT is disabled" | ||
| 12 | #endif | ||
| 13 | |||
| 14 | #include <limits.h> | ||
| 15 | #include <string.h> | ||
| 16 | |||
| 17 | #include <openssl/asn1.h> | ||
| 18 | #include <openssl/buffer.h> | ||
| 19 | #include <openssl/ct.h> | ||
| 20 | #include <openssl/err.h> | ||
| 21 | |||
| 22 | #include "ct_local.h" | ||
| 23 | |||
| 24 | int o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len) | ||
| 25 | { | ||
| 26 | size_t siglen; | ||
| 27 | size_t len_remaining = len; | ||
| 28 | const unsigned char *p; | ||
| 29 | |||
| 30 | if (sct->version != SCT_VERSION_V1) { | ||
| 31 | CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_UNSUPPORTED_VERSION); | ||
| 32 | return -1; | ||
| 33 | } | ||
| 34 | /* | ||
| 35 | * digitally-signed struct header: (1 byte) Hash algorithm (1 byte) | ||
| 36 | * Signature algorithm (2 bytes + ?) Signature | ||
| 37 | * | ||
| 38 | * This explicitly rejects empty signatures: they're invalid for | ||
| 39 | * all supported algorithms. | ||
| 40 | */ | ||
| 41 | if (len <= 4) { | ||
| 42 | CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); | ||
| 43 | return -1; | ||
| 44 | } | ||
| 45 | |||
| 46 | p = *in; | ||
| 47 | /* Get hash and signature algorithm */ | ||
| 48 | sct->hash_alg = *p++; | ||
| 49 | sct->sig_alg = *p++; | ||
| 50 | if (SCT_get_signature_nid(sct) == NID_undef) { | ||
| 51 | CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); | ||
| 52 | return -1; | ||
| 53 | } | ||
| 54 | /* Retrieve signature and check it is consistent with the buffer length */ | ||
| 55 | n2s(p, siglen); | ||
| 56 | len_remaining -= (p - *in); | ||
| 57 | if (siglen > len_remaining) { | ||
| 58 | CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); | ||
| 59 | return -1; | ||
| 60 | } | ||
| 61 | |||
| 62 | if (SCT_set1_signature(sct, p, siglen) != 1) | ||
| 63 | return -1; | ||
| 64 | len_remaining -= siglen; | ||
| 65 | *in = p + siglen; | ||
| 66 | |||
| 67 | return len - len_remaining; | ||
| 68 | } | ||
| 69 | |||
| 70 | SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len) | ||
| 71 | { | ||
| 72 | SCT *sct = NULL; | ||
| 73 | const unsigned char *p; | ||
| 74 | |||
| 75 | if (len == 0 || len > MAX_SCT_SIZE) { | ||
| 76 | CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); | ||
| 77 | goto err; | ||
| 78 | } | ||
| 79 | |||
| 80 | if ((sct = SCT_new()) == NULL) | ||
| 81 | goto err; | ||
| 82 | |||
| 83 | p = *in; | ||
| 84 | |||
| 85 | sct->version = *p; | ||
| 86 | if (sct->version == SCT_VERSION_V1) { | ||
| 87 | int sig_len; | ||
| 88 | size_t len2; | ||
| 89 | /*- | ||
| 90 | * Fixed-length header: | ||
| 91 | * struct { | ||
| 92 | * Version sct_version; (1 byte) | ||
| 93 | * log_id id; (32 bytes) | ||
| 94 | * uint64 timestamp; (8 bytes) | ||
| 95 | * CtExtensions extensions; (2 bytes + ?) | ||
| 96 | * } | ||
| 97 | */ | ||
| 98 | if (len < 43) { | ||
| 99 | CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); | ||
| 100 | goto err; | ||
| 101 | } | ||
| 102 | len -= 43; | ||
| 103 | p++; | ||
| 104 | sct->log_id = BUF_memdup(p, CT_V1_HASHLEN); | ||
| 105 | if (sct->log_id == NULL) | ||
| 106 | goto err; | ||
| 107 | sct->log_id_len = CT_V1_HASHLEN; | ||
| 108 | p += CT_V1_HASHLEN; | ||
| 109 | |||
| 110 | n2l8(p, sct->timestamp); | ||
| 111 | |||
| 112 | n2s(p, len2); | ||
| 113 | if (len < len2) { | ||
| 114 | CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); | ||
| 115 | goto err; | ||
| 116 | } | ||
| 117 | if (len2 > 0) { | ||
| 118 | sct->ext = BUF_memdup(p, len2); | ||
| 119 | if (sct->ext == NULL) | ||
| 120 | goto err; | ||
| 121 | } | ||
| 122 | sct->ext_len = len2; | ||
| 123 | p += len2; | ||
| 124 | len -= len2; | ||
| 125 | |||
| 126 | sig_len = o2i_SCT_signature(sct, &p, len); | ||
| 127 | if (sig_len <= 0) { | ||
| 128 | CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); | ||
| 129 | goto err; | ||
| 130 | } | ||
| 131 | len -= sig_len; | ||
| 132 | *in = p + len; | ||
| 133 | } else { | ||
| 134 | /* If not V1 just cache encoding */ | ||
| 135 | sct->sct = BUF_memdup(p, len); | ||
| 136 | if (sct->sct == NULL) | ||
| 137 | goto err; | ||
| 138 | sct->sct_len = len; | ||
| 139 | *in = p + len; | ||
| 140 | } | ||
| 141 | |||
| 142 | if (psct != NULL) { | ||
| 143 | SCT_free(*psct); | ||
| 144 | *psct = sct; | ||
| 145 | } | ||
| 146 | |||
| 147 | return sct; | ||
| 148 | err: | ||
| 149 | SCT_free(sct); | ||
| 150 | return NULL; | ||
| 151 | } | ||
| 152 | |||
| 153 | int i2o_SCT_signature(const SCT *sct, unsigned char **out) | ||
| 154 | { | ||
| 155 | size_t len; | ||
| 156 | unsigned char *p = NULL, *pstart = NULL; | ||
| 157 | |||
| 158 | if (!SCT_signature_is_complete(sct)) { | ||
| 159 | CTerr(CT_F_I2O_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); | ||
| 160 | goto err; | ||
| 161 | } | ||
| 162 | |||
| 163 | if (sct->version != SCT_VERSION_V1) { | ||
| 164 | CTerr(CT_F_I2O_SCT_SIGNATURE, CT_R_UNSUPPORTED_VERSION); | ||
| 165 | goto err; | ||
| 166 | } | ||
| 167 | |||
| 168 | /* | ||
| 169 | * (1 byte) Hash algorithm | ||
| 170 | * (1 byte) Signature algorithm | ||
| 171 | * (2 bytes + ?) Signature | ||
| 172 | */ | ||
| 173 | len = 4 + sct->sig_len; | ||
| 174 | |||
| 175 | if (out != NULL) { | ||
| 176 | if (*out != NULL) { | ||
| 177 | p = *out; | ||
| 178 | *out += len; | ||
| 179 | } else { | ||
| 180 | pstart = p = OPENSSL_malloc(len); | ||
| 181 | if (p == NULL) { | ||
| 182 | CTerr(CT_F_I2O_SCT_SIGNATURE, ERR_R_MALLOC_FAILURE); | ||
| 183 | goto err; | ||
| 184 | } | ||
| 185 | *out = p; | ||
| 186 | } | ||
| 187 | |||
| 188 | *p++ = sct->hash_alg; | ||
| 189 | *p++ = sct->sig_alg; | ||
| 190 | s2n(sct->sig_len, p); | ||
| 191 | memcpy(p, sct->sig, sct->sig_len); | ||
| 192 | } | ||
| 193 | |||
| 194 | return len; | ||
| 195 | err: | ||
| 196 | OPENSSL_free(pstart); | ||
| 197 | return -1; | ||
| 198 | } | ||
| 199 | |||
| 200 | int i2o_SCT(const SCT *sct, unsigned char **out) | ||
| 201 | { | ||
| 202 | size_t len; | ||
| 203 | unsigned char *p = NULL, *pstart = NULL; | ||
| 204 | |||
| 205 | if (!SCT_is_complete(sct)) { | ||
| 206 | CTerr(CT_F_I2O_SCT, CT_R_SCT_NOT_SET); | ||
| 207 | goto err; | ||
| 208 | } | ||
| 209 | /* | ||
| 210 | * Fixed-length header: struct { (1 byte) Version sct_version; (32 bytes) | ||
| 211 | * log_id id; (8 bytes) uint64 timestamp; (2 bytes + ?) CtExtensions | ||
| 212 | * extensions; (1 byte) Hash algorithm (1 byte) Signature algorithm (2 | ||
| 213 | * bytes + ?) Signature | ||
| 214 | */ | ||
| 215 | if (sct->version == SCT_VERSION_V1) | ||
| 216 | len = 43 + sct->ext_len + 4 + sct->sig_len; | ||
| 217 | else | ||
| 218 | len = sct->sct_len; | ||
| 219 | |||
| 220 | if (out == NULL) | ||
| 221 | return len; | ||
| 222 | |||
| 223 | if (*out != NULL) { | ||
| 224 | p = *out; | ||
| 225 | *out += len; | ||
| 226 | } else { | ||
| 227 | pstart = p = OPENSSL_malloc(len); | ||
| 228 | if (p == NULL) { | ||
| 229 | CTerr(CT_F_I2O_SCT, ERR_R_MALLOC_FAILURE); | ||
| 230 | goto err; | ||
| 231 | } | ||
| 232 | *out = p; | ||
| 233 | } | ||
| 234 | |||
| 235 | if (sct->version == SCT_VERSION_V1) { | ||
| 236 | *p++ = sct->version; | ||
| 237 | memcpy(p, sct->log_id, CT_V1_HASHLEN); | ||
| 238 | p += CT_V1_HASHLEN; | ||
| 239 | l2n8(sct->timestamp, p); | ||
| 240 | s2n(sct->ext_len, p); | ||
| 241 | if (sct->ext_len > 0) { | ||
| 242 | memcpy(p, sct->ext, sct->ext_len); | ||
| 243 | p += sct->ext_len; | ||
| 244 | } | ||
| 245 | if (i2o_SCT_signature(sct, &p) <= 0) | ||
| 246 | goto err; | ||
| 247 | } else { | ||
| 248 | memcpy(p, sct->sct, len); | ||
| 249 | } | ||
| 250 | |||
| 251 | return len; | ||
| 252 | err: | ||
| 253 | OPENSSL_free(pstart); | ||
| 254 | return -1; | ||
| 255 | } | ||
| 256 | |||
| 257 | STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, | ||
| 258 | size_t len) | ||
| 259 | { | ||
| 260 | STACK_OF(SCT) *sk = NULL; | ||
| 261 | size_t list_len, sct_len; | ||
| 262 | |||
| 263 | if (len < 2 || len > MAX_SCT_LIST_SIZE) { | ||
| 264 | CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); | ||
| 265 | return NULL; | ||
| 266 | } | ||
| 267 | |||
| 268 | n2s(*pp, list_len); | ||
| 269 | if (list_len != len - 2) { | ||
| 270 | CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); | ||
| 271 | return NULL; | ||
| 272 | } | ||
| 273 | |||
| 274 | if (a == NULL || *a == NULL) { | ||
| 275 | sk = sk_SCT_new_null(); | ||
| 276 | if (sk == NULL) | ||
| 277 | return NULL; | ||
| 278 | } else { | ||
| 279 | SCT *sct; | ||
| 280 | |||
| 281 | /* Use the given stack, but empty it first. */ | ||
| 282 | sk = *a; | ||
| 283 | while ((sct = sk_SCT_pop(sk)) != NULL) | ||
| 284 | SCT_free(sct); | ||
| 285 | } | ||
| 286 | |||
| 287 | while (list_len > 0) { | ||
| 288 | SCT *sct; | ||
| 289 | |||
| 290 | if (list_len < 2) { | ||
| 291 | CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); | ||
| 292 | goto err; | ||
| 293 | } | ||
| 294 | n2s(*pp, sct_len); | ||
| 295 | list_len -= 2; | ||
| 296 | |||
| 297 | if (sct_len == 0 || sct_len > list_len) { | ||
| 298 | CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); | ||
| 299 | goto err; | ||
| 300 | } | ||
| 301 | list_len -= sct_len; | ||
| 302 | |||
| 303 | if ((sct = o2i_SCT(NULL, pp, sct_len)) == NULL) | ||
| 304 | goto err; | ||
| 305 | if (!sk_SCT_push(sk, sct)) { | ||
| 306 | SCT_free(sct); | ||
| 307 | goto err; | ||
| 308 | } | ||
| 309 | } | ||
| 310 | |||
| 311 | if (a != NULL && *a == NULL) | ||
| 312 | *a = sk; | ||
| 313 | return sk; | ||
| 314 | |||
| 315 | err: | ||
| 316 | if (a == NULL || *a == NULL) | ||
| 317 | SCT_LIST_free(sk); | ||
| 318 | return NULL; | ||
| 319 | } | ||
| 320 | |||
| 321 | int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp) | ||
| 322 | { | ||
| 323 | int len, sct_len, i, is_pp_new = 0; | ||
| 324 | size_t len2; | ||
| 325 | unsigned char *p = NULL, *p2; | ||
| 326 | |||
| 327 | if (pp != NULL) { | ||
| 328 | if (*pp == NULL) { | ||
| 329 | if ((len = i2o_SCT_LIST(a, NULL)) == -1) { | ||
| 330 | CTerr(CT_F_I2O_SCT_LIST, CT_R_SCT_LIST_INVALID); | ||
| 331 | return -1; | ||
| 332 | } | ||
| 333 | if ((*pp = OPENSSL_malloc(len)) == NULL) { | ||
| 334 | CTerr(CT_F_I2O_SCT_LIST, ERR_R_MALLOC_FAILURE); | ||
| 335 | return -1; | ||
| 336 | } | ||
| 337 | is_pp_new = 1; | ||
| 338 | } | ||
| 339 | p = *pp + 2; | ||
| 340 | } | ||
| 341 | |||
| 342 | len2 = 2; | ||
| 343 | for (i = 0; i < sk_SCT_num(a); i++) { | ||
| 344 | if (pp != NULL) { | ||
| 345 | p2 = p; | ||
| 346 | p += 2; | ||
| 347 | if ((sct_len = i2o_SCT(sk_SCT_value(a, i), &p)) == -1) | ||
| 348 | goto err; | ||
| 349 | s2n(sct_len, p2); | ||
| 350 | } else { | ||
| 351 | if ((sct_len = i2o_SCT(sk_SCT_value(a, i), NULL)) == -1) | ||
| 352 | goto err; | ||
| 353 | } | ||
| 354 | len2 += 2 + sct_len; | ||
| 355 | } | ||
| 356 | |||
| 357 | if (len2 > MAX_SCT_LIST_SIZE) | ||
| 358 | goto err; | ||
| 359 | |||
| 360 | if (pp != NULL) { | ||
| 361 | p = *pp; | ||
| 362 | s2n(len2 - 2, p); | ||
| 363 | if (!is_pp_new) | ||
| 364 | *pp += len2; | ||
| 365 | } | ||
| 366 | return len2; | ||
| 367 | |||
| 368 | err: | ||
| 369 | if (is_pp_new) { | ||
| 370 | OPENSSL_free(*pp); | ||
| 371 | *pp = NULL; | ||
| 372 | } | ||
| 373 | return -1; | ||
| 374 | } | ||
| 375 | |||
| 376 | STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, | ||
| 377 | long len) | ||
| 378 | { | ||
| 379 | ASN1_OCTET_STRING *oct = NULL; | ||
| 380 | STACK_OF(SCT) *sk = NULL; | ||
| 381 | const unsigned char *p; | ||
| 382 | |||
| 383 | p = *pp; | ||
| 384 | if (d2i_ASN1_OCTET_STRING(&oct, &p, len) == NULL) | ||
| 385 | return NULL; | ||
| 386 | |||
| 387 | p = oct->data; | ||
| 388 | if ((sk = o2i_SCT_LIST(a, &p, oct->length)) != NULL) | ||
| 389 | *pp += len; | ||
| 390 | |||
| 391 | ASN1_OCTET_STRING_free(oct); | ||
| 392 | return sk; | ||
| 393 | } | ||
| 394 | |||
| 395 | int i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **out) | ||
| 396 | { | ||
| 397 | ASN1_OCTET_STRING oct; | ||
| 398 | int len; | ||
| 399 | |||
| 400 | oct.data = NULL; | ||
| 401 | if ((oct.length = i2o_SCT_LIST(a, &oct.data)) == -1) | ||
| 402 | return -1; | ||
| 403 | |||
| 404 | len = i2d_ASN1_OCTET_STRING(&oct, out); | ||
| 405 | OPENSSL_free(oct.data); | ||
| 406 | return len; | ||
| 407 | } | ||
| diff --git a/src/lib/libcrypto/ct/ct_policy.c b/src/lib/libcrypto/ct/ct_policy.c new file mode 100644 index 0000000000..df66e8a494 --- /dev/null +++ b/src/lib/libcrypto/ct/ct_policy.c | |||
| @@ -0,0 +1,98 @@ | |||
| 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 | #ifdef OPENSSL_NO_CT | ||
| 11 | # error "CT is disabled" | ||
| 12 | #endif | ||
| 13 | |||
| 14 | #include <openssl/ct.h> | ||
| 15 | #include <openssl/err.h> | ||
| 16 | #include <time.h> | ||
| 17 | |||
| 18 | #include "ct_local.h" | ||
| 19 | |||
| 20 | /* | ||
| 21 | * Number of seconds in the future that an SCT timestamp can be, by default, | ||
| 22 | * without being considered invalid. This is added to time() when setting a | ||
| 23 | * default value for CT_POLICY_EVAL_CTX.epoch_time_in_ms. | ||
| 24 | * It can be overridden by calling CT_POLICY_EVAL_CTX_set_time(). | ||
| 25 | */ | ||
| 26 | static const time_t SCT_CLOCK_DRIFT_TOLERANCE = 300; | ||
| 27 | |||
| 28 | CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void) | ||
| 29 | { | ||
| 30 | CT_POLICY_EVAL_CTX *ctx = OPENSSL_zalloc(sizeof(CT_POLICY_EVAL_CTX)); | ||
| 31 | |||
| 32 | if (ctx == NULL) { | ||
| 33 | CTerr(CT_F_CT_POLICY_EVAL_CTX_NEW, ERR_R_MALLOC_FAILURE); | ||
| 34 | return NULL; | ||
| 35 | } | ||
| 36 | |||
| 37 | /* time(NULL) shouldn't ever fail, so don't bother checking for -1. */ | ||
| 38 | ctx->epoch_time_in_ms = (uint64_t)(time(NULL) + SCT_CLOCK_DRIFT_TOLERANCE) * | ||
| 39 | 1000; | ||
| 40 | |||
| 41 | return ctx; | ||
| 42 | } | ||
| 43 | |||
| 44 | void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx) | ||
| 45 | { | ||
| 46 | if (ctx == NULL) | ||
| 47 | return; | ||
| 48 | X509_free(ctx->cert); | ||
| 49 | X509_free(ctx->issuer); | ||
| 50 | OPENSSL_free(ctx); | ||
| 51 | } | ||
| 52 | |||
| 53 | int CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert) | ||
| 54 | { | ||
| 55 | if (!X509_up_ref(cert)) | ||
| 56 | return 0; | ||
| 57 | ctx->cert = cert; | ||
| 58 | return 1; | ||
| 59 | } | ||
| 60 | |||
| 61 | int CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer) | ||
| 62 | { | ||
| 63 | if (!X509_up_ref(issuer)) | ||
| 64 | return 0; | ||
| 65 | ctx->issuer = issuer; | ||
| 66 | return 1; | ||
| 67 | } | ||
| 68 | |||
| 69 | void CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx, | ||
| 70 | CTLOG_STORE *log_store) | ||
| 71 | { | ||
| 72 | ctx->log_store = log_store; | ||
| 73 | } | ||
| 74 | |||
| 75 | void CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms) | ||
| 76 | { | ||
| 77 | ctx->epoch_time_in_ms = time_in_ms; | ||
| 78 | } | ||
| 79 | |||
| 80 | X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx) | ||
| 81 | { | ||
| 82 | return ctx->cert; | ||
| 83 | } | ||
| 84 | |||
| 85 | X509* CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx) | ||
| 86 | { | ||
| 87 | return ctx->issuer; | ||
| 88 | } | ||
| 89 | |||
| 90 | const CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx) | ||
| 91 | { | ||
| 92 | return ctx->log_store; | ||
| 93 | } | ||
| 94 | |||
| 95 | uint64_t CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx) | ||
| 96 | { | ||
| 97 | return ctx->epoch_time_in_ms; | ||
| 98 | } | ||
| diff --git a/src/lib/libcrypto/ct/ct_prn.c b/src/lib/libcrypto/ct/ct_prn.c new file mode 100644 index 0000000000..e6584b57f3 --- /dev/null +++ b/src/lib/libcrypto/ct/ct_prn.c | |||
| @@ -0,0 +1,127 @@ | |||
| 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 | #ifdef OPENSSL_NO_CT | ||
| 11 | # error "CT is disabled" | ||
| 12 | #endif | ||
| 13 | |||
| 14 | #include <openssl/asn1.h> | ||
| 15 | #include <openssl/bio.h> | ||
| 16 | |||
| 17 | #include "ct_local.h" | ||
| 18 | |||
| 19 | static void SCT_signature_algorithms_print(const SCT *sct, BIO *out) | ||
| 20 | { | ||
| 21 | int nid = SCT_get_signature_nid(sct); | ||
| 22 | |||
| 23 | if (nid == NID_undef) | ||
| 24 | BIO_printf(out, "%02X%02X", sct->hash_alg, sct->sig_alg); | ||
| 25 | else | ||
| 26 | BIO_printf(out, "%s", OBJ_nid2ln(nid)); | ||
| 27 | } | ||
| 28 | |||
| 29 | static void timestamp_print(uint64_t timestamp, BIO *out) | ||
| 30 | { | ||
| 31 | ASN1_GENERALIZEDTIME *gen = ASN1_GENERALIZEDTIME_new(); | ||
| 32 | char genstr[20]; | ||
| 33 | |||
| 34 | if (gen == NULL) | ||
| 35 | return; | ||
| 36 | ASN1_GENERALIZEDTIME_adj(gen, (time_t)0, | ||
| 37 | (int)(timestamp / 86400000), | ||
| 38 | (timestamp % 86400000) / 1000); | ||
| 39 | /* | ||
| 40 | * Note GeneralizedTime from ASN1_GENERALIZETIME_adj is always 15 | ||
| 41 | * characters long with a final Z. Update it with fractional seconds. | ||
| 42 | */ | ||
| 43 | BIO_snprintf(genstr, sizeof(genstr), "%.14s.%03dZ", | ||
| 44 | ASN1_STRING_get0_data(gen), (unsigned int)(timestamp % 1000)); | ||
| 45 | if (ASN1_GENERALIZEDTIME_set_string(gen, genstr)) | ||
| 46 | ASN1_GENERALIZEDTIME_print(out, gen); | ||
| 47 | ASN1_GENERALIZEDTIME_free(gen); | ||
| 48 | } | ||
| 49 | |||
| 50 | const char *SCT_validation_status_string(const SCT *sct) | ||
| 51 | { | ||
| 52 | |||
| 53 | switch (SCT_get_validation_status(sct)) { | ||
| 54 | case SCT_VALIDATION_STATUS_NOT_SET: | ||
| 55 | return "not set"; | ||
| 56 | case SCT_VALIDATION_STATUS_UNKNOWN_VERSION: | ||
| 57 | return "unknown version"; | ||
| 58 | case SCT_VALIDATION_STATUS_UNKNOWN_LOG: | ||
| 59 | return "unknown log"; | ||
| 60 | case SCT_VALIDATION_STATUS_UNVERIFIED: | ||
| 61 | return "unverified"; | ||
| 62 | case SCT_VALIDATION_STATUS_INVALID: | ||
| 63 | return "invalid"; | ||
| 64 | case SCT_VALIDATION_STATUS_VALID: | ||
| 65 | return "valid"; | ||
| 66 | } | ||
| 67 | return "unknown status"; | ||
| 68 | } | ||
| 69 | |||
| 70 | void SCT_print(const SCT *sct, BIO *out, int indent, | ||
| 71 | const CTLOG_STORE *log_store) | ||
| 72 | { | ||
| 73 | const CTLOG *log = NULL; | ||
| 74 | |||
| 75 | if (log_store != NULL) { | ||
| 76 | log = CTLOG_STORE_get0_log_by_id(log_store, sct->log_id, | ||
| 77 | sct->log_id_len); | ||
| 78 | } | ||
| 79 | |||
| 80 | BIO_printf(out, "%*sSigned Certificate Timestamp:", indent, ""); | ||
| 81 | BIO_printf(out, "\n%*sVersion : ", indent + 4, ""); | ||
| 82 | |||
| 83 | if (sct->version != SCT_VERSION_V1) { | ||
| 84 | BIO_printf(out, "unknown\n%*s", indent + 16, ""); | ||
| 85 | BIO_hex_string(out, indent + 16, 16, sct->sct, sct->sct_len); | ||
| 86 | return; | ||
| 87 | } | ||
| 88 | |||
| 89 | BIO_printf(out, "v1 (0x0)"); | ||
| 90 | |||
| 91 | if (log != NULL) { | ||
| 92 | BIO_printf(out, "\n%*sLog : %s", indent + 4, "", | ||
| 93 | CTLOG_get0_name(log)); | ||
| 94 | } | ||
| 95 | |||
| 96 | BIO_printf(out, "\n%*sLog ID : ", indent + 4, ""); | ||
| 97 | BIO_hex_string(out, indent + 16, 16, sct->log_id, sct->log_id_len); | ||
| 98 | |||
| 99 | BIO_printf(out, "\n%*sTimestamp : ", indent + 4, ""); | ||
| 100 | timestamp_print(sct->timestamp, out); | ||
| 101 | |||
| 102 | BIO_printf(out, "\n%*sExtensions: ", indent + 4, ""); | ||
| 103 | if (sct->ext_len == 0) | ||
| 104 | BIO_printf(out, "none"); | ||
| 105 | else | ||
| 106 | BIO_hex_string(out, indent + 16, 16, sct->ext, sct->ext_len); | ||
| 107 | |||
| 108 | BIO_printf(out, "\n%*sSignature : ", indent + 4, ""); | ||
| 109 | SCT_signature_algorithms_print(sct, out); | ||
| 110 | BIO_printf(out, "\n%*s ", indent + 4, ""); | ||
| 111 | BIO_hex_string(out, indent + 16, 16, sct->sig, sct->sig_len); | ||
| 112 | } | ||
| 113 | |||
| 114 | void SCT_LIST_print(const STACK_OF(SCT) *sct_list, BIO *out, int indent, | ||
| 115 | const char *separator, const CTLOG_STORE *log_store) | ||
| 116 | { | ||
| 117 | int sct_count = sk_SCT_num(sct_list); | ||
| 118 | int i; | ||
| 119 | |||
| 120 | for (i = 0; i < sct_count; ++i) { | ||
| 121 | SCT *sct = sk_SCT_value(sct_list, i); | ||
| 122 | |||
| 123 | SCT_print(sct, out, indent, log_store); | ||
| 124 | if (i < sk_SCT_num(sct_list) - 1) | ||
| 125 | BIO_printf(out, "%s", separator); | ||
| 126 | } | ||
| 127 | } | ||
| diff --git a/src/lib/libcrypto/ct/ct_sct.c b/src/lib/libcrypto/ct/ct_sct.c new file mode 100644 index 0000000000..4ff36e2fbd --- /dev/null +++ b/src/lib/libcrypto/ct/ct_sct.c | |||
| @@ -0,0 +1,396 @@ | |||
| 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 | #ifdef OPENSSL_NO_CT | ||
| 11 | # error "CT disabled" | ||
| 12 | #endif | ||
| 13 | |||
| 14 | #include <openssl/ct.h> | ||
| 15 | #include <openssl/err.h> | ||
| 16 | #include <openssl/evp.h> | ||
| 17 | #include <openssl/tls1.h> | ||
| 18 | #include <openssl/x509.h> | ||
| 19 | |||
| 20 | #include "ct_local.h" | ||
| 21 | |||
| 22 | SCT *SCT_new(void) | ||
| 23 | { | ||
| 24 | SCT *sct = OPENSSL_zalloc(sizeof(*sct)); | ||
| 25 | |||
| 26 | if (sct == NULL) { | ||
| 27 | CTerr(CT_F_SCT_NEW, ERR_R_MALLOC_FAILURE); | ||
| 28 | return NULL; | ||
| 29 | } | ||
| 30 | |||
| 31 | sct->entry_type = CT_LOG_ENTRY_TYPE_NOT_SET; | ||
| 32 | sct->version = SCT_VERSION_NOT_SET; | ||
| 33 | return sct; | ||
| 34 | } | ||
| 35 | |||
| 36 | void SCT_free(SCT *sct) | ||
| 37 | { | ||
| 38 | if (sct == NULL) | ||
| 39 | return; | ||
| 40 | |||
| 41 | OPENSSL_free(sct->log_id); | ||
| 42 | OPENSSL_free(sct->ext); | ||
| 43 | OPENSSL_free(sct->sig); | ||
| 44 | OPENSSL_free(sct->sct); | ||
| 45 | OPENSSL_free(sct); | ||
| 46 | } | ||
| 47 | |||
| 48 | void SCT_LIST_free(STACK_OF(SCT) *a) | ||
| 49 | { | ||
| 50 | sk_SCT_pop_free(a, SCT_free); | ||
| 51 | } | ||
| 52 | |||
| 53 | int SCT_set_version(SCT *sct, sct_version_t version) | ||
| 54 | { | ||
| 55 | if (version != SCT_VERSION_V1) { | ||
| 56 | CTerr(CT_F_SCT_SET_VERSION, CT_R_UNSUPPORTED_VERSION); | ||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | sct->version = version; | ||
| 60 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 61 | return 1; | ||
| 62 | } | ||
| 63 | |||
| 64 | int SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type) | ||
| 65 | { | ||
| 66 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 67 | |||
| 68 | switch (entry_type) { | ||
| 69 | case CT_LOG_ENTRY_TYPE_X509: | ||
| 70 | case CT_LOG_ENTRY_TYPE_PRECERT: | ||
| 71 | sct->entry_type = entry_type; | ||
| 72 | return 1; | ||
| 73 | case CT_LOG_ENTRY_TYPE_NOT_SET: | ||
| 74 | break; | ||
| 75 | } | ||
| 76 | CTerr(CT_F_SCT_SET_LOG_ENTRY_TYPE, CT_R_UNSUPPORTED_ENTRY_TYPE); | ||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | int SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len) | ||
| 81 | { | ||
| 82 | if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) { | ||
| 83 | CTerr(CT_F_SCT_SET0_LOG_ID, CT_R_INVALID_LOG_ID_LENGTH); | ||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | OPENSSL_free(sct->log_id); | ||
| 88 | sct->log_id = log_id; | ||
| 89 | sct->log_id_len = log_id_len; | ||
| 90 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 91 | return 1; | ||
| 92 | } | ||
| 93 | |||
| 94 | int SCT_set1_log_id(SCT *sct, const unsigned char *log_id, size_t log_id_len) | ||
| 95 | { | ||
| 96 | if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) { | ||
| 97 | CTerr(CT_F_SCT_SET1_LOG_ID, CT_R_INVALID_LOG_ID_LENGTH); | ||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | OPENSSL_free(sct->log_id); | ||
| 102 | sct->log_id = NULL; | ||
| 103 | sct->log_id_len = 0; | ||
| 104 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 105 | |||
| 106 | if (log_id != NULL && log_id_len > 0) { | ||
| 107 | sct->log_id = OPENSSL_memdup(log_id, log_id_len); | ||
| 108 | if (sct->log_id == NULL) { | ||
| 109 | CTerr(CT_F_SCT_SET1_LOG_ID, ERR_R_MALLOC_FAILURE); | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | sct->log_id_len = log_id_len; | ||
| 113 | } | ||
| 114 | return 1; | ||
| 115 | } | ||
| 116 | |||
| 117 | |||
| 118 | void SCT_set_timestamp(SCT *sct, uint64_t timestamp) | ||
| 119 | { | ||
| 120 | sct->timestamp = timestamp; | ||
| 121 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 122 | } | ||
| 123 | |||
| 124 | int SCT_set_signature_nid(SCT *sct, int nid) | ||
| 125 | { | ||
| 126 | switch (nid) { | ||
| 127 | case NID_sha256WithRSAEncryption: | ||
| 128 | sct->hash_alg = TLSEXT_hash_sha256; | ||
| 129 | sct->sig_alg = TLSEXT_signature_rsa; | ||
| 130 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 131 | return 1; | ||
| 132 | case NID_ecdsa_with_SHA256: | ||
| 133 | sct->hash_alg = TLSEXT_hash_sha256; | ||
| 134 | sct->sig_alg = TLSEXT_signature_ecdsa; | ||
| 135 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 136 | return 1; | ||
| 137 | default: | ||
| 138 | CTerr(CT_F_SCT_SET_SIGNATURE_NID, CT_R_UNRECOGNIZED_SIGNATURE_NID); | ||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | void SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len) | ||
| 144 | { | ||
| 145 | OPENSSL_free(sct->ext); | ||
| 146 | sct->ext = ext; | ||
| 147 | sct->ext_len = ext_len; | ||
| 148 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 149 | } | ||
| 150 | |||
| 151 | int SCT_set1_extensions(SCT *sct, const unsigned char *ext, size_t ext_len) | ||
| 152 | { | ||
| 153 | OPENSSL_free(sct->ext); | ||
| 154 | sct->ext = NULL; | ||
| 155 | sct->ext_len = 0; | ||
| 156 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 157 | |||
| 158 | if (ext != NULL && ext_len > 0) { | ||
| 159 | sct->ext = OPENSSL_memdup(ext, ext_len); | ||
| 160 | if (sct->ext == NULL) { | ||
| 161 | CTerr(CT_F_SCT_SET1_EXTENSIONS, ERR_R_MALLOC_FAILURE); | ||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | sct->ext_len = ext_len; | ||
| 165 | } | ||
| 166 | return 1; | ||
| 167 | } | ||
| 168 | |||
| 169 | void SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len) | ||
| 170 | { | ||
| 171 | OPENSSL_free(sct->sig); | ||
| 172 | sct->sig = sig; | ||
| 173 | sct->sig_len = sig_len; | ||
| 174 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 175 | } | ||
| 176 | |||
| 177 | int SCT_set1_signature(SCT *sct, const unsigned char *sig, size_t sig_len) | ||
| 178 | { | ||
| 179 | OPENSSL_free(sct->sig); | ||
| 180 | sct->sig = NULL; | ||
| 181 | sct->sig_len = 0; | ||
| 182 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 183 | |||
| 184 | if (sig != NULL && sig_len > 0) { | ||
| 185 | sct->sig = OPENSSL_memdup(sig, sig_len); | ||
| 186 | if (sct->sig == NULL) { | ||
| 187 | CTerr(CT_F_SCT_SET1_SIGNATURE, ERR_R_MALLOC_FAILURE); | ||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | sct->sig_len = sig_len; | ||
| 191 | } | ||
| 192 | return 1; | ||
| 193 | } | ||
| 194 | |||
| 195 | sct_version_t SCT_get_version(const SCT *sct) | ||
| 196 | { | ||
| 197 | return sct->version; | ||
| 198 | } | ||
| 199 | |||
| 200 | ct_log_entry_type_t SCT_get_log_entry_type(const SCT *sct) | ||
| 201 | { | ||
| 202 | return sct->entry_type; | ||
| 203 | } | ||
| 204 | |||
| 205 | size_t SCT_get0_log_id(const SCT *sct, unsigned char **log_id) | ||
| 206 | { | ||
| 207 | *log_id = sct->log_id; | ||
| 208 | return sct->log_id_len; | ||
| 209 | } | ||
| 210 | |||
| 211 | uint64_t SCT_get_timestamp(const SCT *sct) | ||
| 212 | { | ||
| 213 | return sct->timestamp; | ||
| 214 | } | ||
| 215 | |||
| 216 | int SCT_get_signature_nid(const SCT *sct) | ||
| 217 | { | ||
| 218 | if (sct->version == SCT_VERSION_V1) { | ||
| 219 | if (sct->hash_alg == TLSEXT_hash_sha256) { | ||
| 220 | switch (sct->sig_alg) { | ||
| 221 | case TLSEXT_signature_ecdsa: | ||
| 222 | return NID_ecdsa_with_SHA256; | ||
| 223 | case TLSEXT_signature_rsa: | ||
| 224 | return NID_sha256WithRSAEncryption; | ||
| 225 | default: | ||
| 226 | return NID_undef; | ||
| 227 | } | ||
| 228 | } | ||
| 229 | } | ||
| 230 | return NID_undef; | ||
| 231 | } | ||
| 232 | |||
| 233 | size_t SCT_get0_extensions(const SCT *sct, unsigned char **ext) | ||
| 234 | { | ||
| 235 | *ext = sct->ext; | ||
| 236 | return sct->ext_len; | ||
| 237 | } | ||
| 238 | |||
| 239 | size_t SCT_get0_signature(const SCT *sct, unsigned char **sig) | ||
| 240 | { | ||
| 241 | *sig = sct->sig; | ||
| 242 | return sct->sig_len; | ||
| 243 | } | ||
| 244 | |||
| 245 | int SCT_is_complete(const SCT *sct) | ||
| 246 | { | ||
| 247 | switch (sct->version) { | ||
| 248 | case SCT_VERSION_NOT_SET: | ||
| 249 | return 0; | ||
| 250 | case SCT_VERSION_V1: | ||
| 251 | return sct->log_id != NULL && SCT_signature_is_complete(sct); | ||
| 252 | default: | ||
| 253 | return sct->sct != NULL; /* Just need cached encoding */ | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | int SCT_signature_is_complete(const SCT *sct) | ||
| 258 | { | ||
| 259 | return SCT_get_signature_nid(sct) != NID_undef && | ||
| 260 | sct->sig != NULL && sct->sig_len > 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | sct_source_t SCT_get_source(const SCT *sct) | ||
| 264 | { | ||
| 265 | return sct->source; | ||
| 266 | } | ||
| 267 | |||
| 268 | int SCT_set_source(SCT *sct, sct_source_t source) | ||
| 269 | { | ||
| 270 | sct->source = source; | ||
| 271 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; | ||
| 272 | switch (source) { | ||
| 273 | case SCT_SOURCE_TLS_EXTENSION: | ||
| 274 | case SCT_SOURCE_OCSP_STAPLED_RESPONSE: | ||
| 275 | return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_X509); | ||
| 276 | case SCT_SOURCE_X509V3_EXTENSION: | ||
| 277 | return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_PRECERT); | ||
| 278 | case SCT_SOURCE_UNKNOWN: | ||
| 279 | break; | ||
| 280 | } | ||
| 281 | /* if we aren't sure, leave the log entry type alone */ | ||
| 282 | return 1; | ||
| 283 | } | ||
| 284 | |||
| 285 | sct_validation_status_t SCT_get_validation_status(const SCT *sct) | ||
| 286 | { | ||
| 287 | return sct->validation_status; | ||
| 288 | } | ||
| 289 | |||
| 290 | int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx) | ||
| 291 | { | ||
| 292 | int is_sct_valid = -1; | ||
| 293 | SCT_CTX *sctx = NULL; | ||
| 294 | X509_PUBKEY *pub = NULL, *log_pkey = NULL; | ||
| 295 | const CTLOG *log; | ||
| 296 | |||
| 297 | /* | ||
| 298 | * With an unrecognized SCT version we don't know what such an SCT means, | ||
| 299 | * let alone validate one. So we return validation failure (0). | ||
| 300 | */ | ||
| 301 | if (sct->version != SCT_VERSION_V1) { | ||
| 302 | sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_VERSION; | ||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | log = CTLOG_STORE_get0_log_by_id(ctx->log_store, | ||
| 307 | sct->log_id, sct->log_id_len); | ||
| 308 | |||
| 309 | /* Similarly, an SCT from an unknown log also cannot be validated. */ | ||
| 310 | if (log == NULL) { | ||
| 311 | sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_LOG; | ||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | |||
| 315 | sctx = SCT_CTX_new(); | ||
| 316 | if (sctx == NULL) | ||
| 317 | goto err; | ||
| 318 | |||
| 319 | if (X509_PUBKEY_set(&log_pkey, CTLOG_get0_public_key(log)) != 1) | ||
| 320 | goto err; | ||
| 321 | if (SCT_CTX_set1_pubkey(sctx, log_pkey) != 1) | ||
| 322 | goto err; | ||
| 323 | |||
| 324 | if (SCT_get_log_entry_type(sct) == CT_LOG_ENTRY_TYPE_PRECERT) { | ||
| 325 | EVP_PKEY *issuer_pkey; | ||
| 326 | |||
| 327 | if (ctx->issuer == NULL) { | ||
| 328 | sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED; | ||
| 329 | goto end; | ||
| 330 | } | ||
| 331 | |||
| 332 | issuer_pkey = X509_get0_pubkey(ctx->issuer); | ||
| 333 | |||
| 334 | if (X509_PUBKEY_set(&pub, issuer_pkey) != 1) | ||
| 335 | goto err; | ||
| 336 | if (SCT_CTX_set1_issuer_pubkey(sctx, pub) != 1) | ||
| 337 | goto err; | ||
| 338 | } | ||
| 339 | |||
| 340 | SCT_CTX_set_time(sctx, ctx->epoch_time_in_ms); | ||
| 341 | |||
| 342 | /* | ||
| 343 | * XXX: Potential for optimization. This repeats some idempotent heavy | ||
| 344 | * lifting on the certificate for each candidate SCT, and appears to not | ||
| 345 | * use any information in the SCT itself, only the certificate is | ||
| 346 | * processed. So it may make more sense to to do this just once, perhaps | ||
| 347 | * associated with the shared (by all SCTs) policy eval ctx. | ||
| 348 | * | ||
| 349 | * XXX: Failure here is global (SCT independent) and represents either an | ||
| 350 | * issue with the certificate (e.g. duplicate extensions) or an out of | ||
| 351 | * memory condition. When the certificate is incompatible with CT, we just | ||
| 352 | * mark the SCTs invalid, rather than report a failure to determine the | ||
| 353 | * validation status. That way, callbacks that want to do "soft" SCT | ||
| 354 | * processing will not abort handshakes with false positive internal | ||
| 355 | * errors. Since the function does not distinguish between certificate | ||
| 356 | * issues (peer's fault) and internal problems (out fault) the safe thing | ||
| 357 | * to do is to report a validation failure and let the callback or | ||
| 358 | * application decide what to do. | ||
| 359 | */ | ||
| 360 | if (SCT_CTX_set1_cert(sctx, ctx->cert, NULL) != 1) | ||
| 361 | sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED; | ||
| 362 | else | ||
| 363 | sct->validation_status = SCT_CTX_verify(sctx, sct) == 1 ? | ||
| 364 | SCT_VALIDATION_STATUS_VALID : SCT_VALIDATION_STATUS_INVALID; | ||
| 365 | |||
| 366 | end: | ||
| 367 | is_sct_valid = sct->validation_status == SCT_VALIDATION_STATUS_VALID; | ||
| 368 | err: | ||
| 369 | X509_PUBKEY_free(pub); | ||
| 370 | X509_PUBKEY_free(log_pkey); | ||
| 371 | SCT_CTX_free(sctx); | ||
| 372 | |||
| 373 | return is_sct_valid; | ||
| 374 | } | ||
| 375 | |||
| 376 | int SCT_LIST_validate(const STACK_OF(SCT) *scts, CT_POLICY_EVAL_CTX *ctx) | ||
| 377 | { | ||
| 378 | int are_scts_valid = 1; | ||
| 379 | int sct_count = scts != NULL ? sk_SCT_num(scts) : 0; | ||
| 380 | int i; | ||
| 381 | |||
| 382 | for (i = 0; i < sct_count; ++i) { | ||
| 383 | int is_sct_valid = -1; | ||
| 384 | SCT *sct = sk_SCT_value(scts, i); | ||
| 385 | |||
| 386 | if (sct == NULL) | ||
| 387 | continue; | ||
| 388 | |||
| 389 | is_sct_valid = SCT_validate(sct, ctx); | ||
| 390 | if (is_sct_valid < 0) | ||
| 391 | return is_sct_valid; | ||
| 392 | are_scts_valid &= is_sct_valid; | ||
| 393 | } | ||
| 394 | |||
| 395 | return are_scts_valid; | ||
| 396 | } | ||
| diff --git a/src/lib/libcrypto/ct/ct_sct_ctx.c b/src/lib/libcrypto/ct/ct_sct_ctx.c new file mode 100644 index 0000000000..841e768033 --- /dev/null +++ b/src/lib/libcrypto/ct/ct_sct_ctx.c | |||
| @@ -0,0 +1,263 @@ | |||
| 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 | #ifdef OPENSSL_NO_CT | ||
| 11 | # error "CT is disabled" | ||
| 12 | #endif | ||
| 13 | |||
| 14 | #include <stddef.h> | ||
| 15 | #include <string.h> | ||
| 16 | |||
| 17 | #include <openssl/err.h> | ||
| 18 | #include <openssl/obj_mac.h> | ||
| 19 | #include <openssl/x509.h> | ||
| 20 | |||
| 21 | #include "ct_local.h" | ||
| 22 | |||
| 23 | SCT_CTX *SCT_CTX_new(void) | ||
| 24 | { | ||
| 25 | SCT_CTX *sctx = OPENSSL_zalloc(sizeof(*sctx)); | ||
| 26 | |||
| 27 | if (sctx == NULL) | ||
| 28 | CTerr(CT_F_SCT_CTX_NEW, ERR_R_MALLOC_FAILURE); | ||
| 29 | |||
| 30 | return sctx; | ||
| 31 | } | ||
| 32 | |||
| 33 | void SCT_CTX_free(SCT_CTX *sctx) | ||
| 34 | { | ||
| 35 | if (sctx == NULL) | ||
| 36 | return; | ||
| 37 | EVP_PKEY_free(sctx->pkey); | ||
| 38 | OPENSSL_free(sctx->pkeyhash); | ||
| 39 | OPENSSL_free(sctx->ihash); | ||
| 40 | OPENSSL_free(sctx->certder); | ||
| 41 | OPENSSL_free(sctx->preder); | ||
| 42 | OPENSSL_free(sctx); | ||
| 43 | } | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Finds the index of the first extension with the given NID in cert. | ||
| 47 | * If there is more than one extension with that NID, *is_duplicated is set to | ||
| 48 | * 1, otherwise 0 (unless it is NULL). | ||
| 49 | */ | ||
| 50 | static int ct_x509_get_ext(X509 *cert, int nid, int *is_duplicated) | ||
| 51 | { | ||
| 52 | int ret = X509_get_ext_by_NID(cert, nid, -1); | ||
| 53 | |||
| 54 | if (is_duplicated != NULL) | ||
| 55 | *is_duplicated = ret >= 0 && X509_get_ext_by_NID(cert, nid, ret) >= 0; | ||
| 56 | |||
| 57 | return ret; | ||
| 58 | } | ||
| 59 | |||
| 60 | /* | ||
| 61 | * Modifies a certificate by deleting extensions and copying the issuer and | ||
| 62 | * AKID from the presigner certificate, if necessary. | ||
| 63 | * Returns 1 on success, 0 otherwise. | ||
| 64 | */ | ||
| 65 | __owur static int ct_x509_cert_fixup(X509 *cert, X509 *presigner) | ||
| 66 | { | ||
| 67 | int preidx, certidx; | ||
| 68 | int pre_akid_ext_is_dup, cert_akid_ext_is_dup; | ||
| 69 | |||
| 70 | if (presigner == NULL) | ||
| 71 | return 1; | ||
| 72 | |||
| 73 | preidx = ct_x509_get_ext(presigner, NID_authority_key_identifier, | ||
| 74 | &pre_akid_ext_is_dup); | ||
| 75 | certidx = ct_x509_get_ext(cert, NID_authority_key_identifier, | ||
| 76 | &cert_akid_ext_is_dup); | ||
| 77 | |||
| 78 | /* An error occurred whilst searching for the extension */ | ||
| 79 | if (preidx < -1 || certidx < -1) | ||
| 80 | return 0; | ||
| 81 | /* Invalid certificate if they contain duplicate extensions */ | ||
| 82 | if (pre_akid_ext_is_dup || cert_akid_ext_is_dup) | ||
| 83 | return 0; | ||
| 84 | /* AKID must be present in both certificate or absent in both */ | ||
| 85 | if (preidx >= 0 && certidx == -1) | ||
| 86 | return 0; | ||
| 87 | if (preidx == -1 && certidx >= 0) | ||
| 88 | return 0; | ||
| 89 | /* Copy issuer name */ | ||
| 90 | if (!X509_set_issuer_name(cert, X509_get_issuer_name(presigner))) | ||
| 91 | return 0; | ||
| 92 | if (preidx != -1) { | ||
| 93 | /* Retrieve and copy AKID encoding */ | ||
| 94 | X509_EXTENSION *preext = X509_get_ext(presigner, preidx); | ||
| 95 | X509_EXTENSION *certext = X509_get_ext(cert, certidx); | ||
| 96 | ASN1_OCTET_STRING *preextdata; | ||
| 97 | |||
| 98 | /* Should never happen */ | ||
| 99 | if (preext == NULL || certext == NULL) | ||
| 100 | return 0; | ||
| 101 | preextdata = X509_EXTENSION_get_data(preext); | ||
| 102 | if (preextdata == NULL || | ||
| 103 | !X509_EXTENSION_set_data(certext, preextdata)) | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | return 1; | ||
| 107 | } | ||
| 108 | |||
| 109 | int SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner) | ||
| 110 | { | ||
| 111 | unsigned char *certder = NULL, *preder = NULL; | ||
| 112 | X509 *pretmp = NULL; | ||
| 113 | int certderlen = 0, prederlen = 0; | ||
| 114 | int idx = -1; | ||
| 115 | int poison_ext_is_dup, sct_ext_is_dup; | ||
| 116 | int poison_idx = ct_x509_get_ext(cert, NID_ct_precert_poison, &poison_ext_is_dup); | ||
| 117 | |||
| 118 | /* Duplicate poison extensions are present - error */ | ||
| 119 | if (poison_ext_is_dup) | ||
| 120 | goto err; | ||
| 121 | |||
| 122 | /* If *cert doesn't have a poison extension, it isn't a precert */ | ||
| 123 | if (poison_idx == -1) { | ||
| 124 | /* cert isn't a precert, so we shouldn't have a presigner */ | ||
| 125 | if (presigner != NULL) | ||
| 126 | goto err; | ||
| 127 | |||
| 128 | certderlen = i2d_X509(cert, &certder); | ||
| 129 | if (certderlen < 0) | ||
| 130 | goto err; | ||
| 131 | } | ||
| 132 | |||
| 133 | /* See if cert has a precert SCTs extension */ | ||
| 134 | idx = ct_x509_get_ext(cert, NID_ct_precert_scts, &sct_ext_is_dup); | ||
| 135 | /* Duplicate SCT extensions are present - error */ | ||
| 136 | if (sct_ext_is_dup) | ||
| 137 | goto err; | ||
| 138 | |||
| 139 | if (idx >= 0 && poison_idx >= 0) { | ||
| 140 | /* | ||
| 141 | * cert can't both contain SCTs (i.e. have an SCT extension) and be a | ||
| 142 | * precert (i.e. have a poison extension). | ||
| 143 | */ | ||
| 144 | goto err; | ||
| 145 | } | ||
| 146 | |||
| 147 | if (idx == -1) { | ||
| 148 | idx = poison_idx; | ||
| 149 | } | ||
| 150 | |||
| 151 | /* | ||
| 152 | * If either a poison or SCT extension is present, remove it before encoding | ||
| 153 | * cert. This, along with ct_x509_cert_fixup(), gets a TBSCertificate (see | ||
| 154 | * RFC5280) from cert, which is what the CT log signed when it produced the | ||
| 155 | * SCT. | ||
| 156 | */ | ||
| 157 | if (idx >= 0) { | ||
| 158 | X509_EXTENSION *ext; | ||
| 159 | |||
| 160 | /* Take a copy of certificate so we don't modify passed version */ | ||
| 161 | pretmp = X509_dup(cert); | ||
| 162 | if (pretmp == NULL) | ||
| 163 | goto err; | ||
| 164 | |||
| 165 | ext = X509_delete_ext(pretmp, idx); | ||
| 166 | X509_EXTENSION_free(ext); | ||
| 167 | |||
| 168 | if (!ct_x509_cert_fixup(pretmp, presigner)) | ||
| 169 | goto err; | ||
| 170 | |||
| 171 | prederlen = i2d_re_X509_tbs(pretmp, &preder); | ||
| 172 | if (prederlen <= 0) | ||
| 173 | goto err; | ||
| 174 | } | ||
| 175 | |||
| 176 | X509_free(pretmp); | ||
| 177 | |||
| 178 | OPENSSL_free(sctx->certder); | ||
| 179 | sctx->certder = certder; | ||
| 180 | sctx->certderlen = certderlen; | ||
| 181 | |||
| 182 | OPENSSL_free(sctx->preder); | ||
| 183 | sctx->preder = preder; | ||
| 184 | sctx->prederlen = prederlen; | ||
| 185 | |||
| 186 | return 1; | ||
| 187 | err: | ||
| 188 | OPENSSL_free(certder); | ||
| 189 | OPENSSL_free(preder); | ||
| 190 | X509_free(pretmp); | ||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | __owur static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash, | ||
| 195 | size_t *hash_len) | ||
| 196 | { | ||
| 197 | int ret = 0; | ||
| 198 | unsigned char *md = NULL, *der = NULL; | ||
| 199 | int der_len; | ||
| 200 | unsigned int md_len; | ||
| 201 | |||
| 202 | /* Reuse buffer if possible */ | ||
| 203 | if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) { | ||
| 204 | md = *hash; | ||
| 205 | } else { | ||
| 206 | md = OPENSSL_malloc(SHA256_DIGEST_LENGTH); | ||
| 207 | if (md == NULL) | ||
| 208 | goto err; | ||
| 209 | } | ||
| 210 | |||
| 211 | /* Calculate key hash */ | ||
| 212 | der_len = i2d_X509_PUBKEY(pkey, &der); | ||
| 213 | if (der_len <= 0) | ||
| 214 | goto err; | ||
| 215 | |||
| 216 | if (!EVP_Digest(der, der_len, md, &md_len, EVP_sha256(), NULL)) | ||
| 217 | goto err; | ||
| 218 | |||
| 219 | if (md != *hash) { | ||
| 220 | OPENSSL_free(*hash); | ||
| 221 | *hash = md; | ||
| 222 | *hash_len = SHA256_DIGEST_LENGTH; | ||
| 223 | } | ||
| 224 | |||
| 225 | md = NULL; | ||
| 226 | ret = 1; | ||
| 227 | err: | ||
| 228 | OPENSSL_free(md); | ||
| 229 | OPENSSL_free(der); | ||
| 230 | return ret; | ||
| 231 | } | ||
| 232 | |||
| 233 | int SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer) | ||
| 234 | { | ||
| 235 | return SCT_CTX_set1_issuer_pubkey(sctx, X509_get_X509_PUBKEY(issuer)); | ||
| 236 | } | ||
| 237 | |||
| 238 | int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey) | ||
| 239 | { | ||
| 240 | return ct_public_key_hash(pubkey, &sctx->ihash, &sctx->ihashlen); | ||
| 241 | } | ||
| 242 | |||
| 243 | int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey) | ||
| 244 | { | ||
| 245 | EVP_PKEY *pkey = X509_PUBKEY_get(pubkey); | ||
| 246 | |||
| 247 | if (pkey == NULL) | ||
| 248 | return 0; | ||
| 249 | |||
| 250 | if (!ct_public_key_hash(pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) { | ||
| 251 | EVP_PKEY_free(pkey); | ||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | |||
| 255 | EVP_PKEY_free(sctx->pkey); | ||
| 256 | sctx->pkey = pkey; | ||
| 257 | return 1; | ||
| 258 | } | ||
| 259 | |||
| 260 | void SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms) | ||
| 261 | { | ||
| 262 | sctx->epoch_time_in_ms = time_in_ms; | ||
| 263 | } | ||
| diff --git a/src/lib/libcrypto/ct/ct_vfy.c b/src/lib/libcrypto/ct/ct_vfy.c new file mode 100644 index 0000000000..74fd34f415 --- /dev/null +++ b/src/lib/libcrypto/ct/ct_vfy.c | |||
| @@ -0,0 +1,140 @@ | |||
| 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 <string.h> | ||
| 11 | |||
| 12 | #include <openssl/ct.h> | ||
| 13 | #include <openssl/err.h> | ||
| 14 | #include <openssl/evp.h> | ||
| 15 | #include <openssl/x509.h> | ||
| 16 | |||
| 17 | #include "ct_local.h" | ||
| 18 | |||
| 19 | typedef enum sct_signature_type_t { | ||
| 20 | SIGNATURE_TYPE_NOT_SET = -1, | ||
| 21 | SIGNATURE_TYPE_CERT_TIMESTAMP, | ||
| 22 | SIGNATURE_TYPE_TREE_HASH | ||
| 23 | } SCT_SIGNATURE_TYPE; | ||
| 24 | |||
| 25 | /* | ||
| 26 | * Update encoding for SCT signature verification/generation to supplied | ||
| 27 | * EVP_MD_CTX. | ||
| 28 | */ | ||
| 29 | static int sct_ctx_update(EVP_MD_CTX *ctx, const SCT_CTX *sctx, const SCT *sct) | ||
| 30 | { | ||
| 31 | unsigned char tmpbuf[12]; | ||
| 32 | unsigned char *p, *der; | ||
| 33 | size_t derlen; | ||
| 34 | /*+ | ||
| 35 | * digitally-signed struct { | ||
| 36 | * (1 byte) Version sct_version; | ||
| 37 | * (1 byte) SignatureType signature_type = certificate_timestamp; | ||
| 38 | * (8 bytes) uint64 timestamp; | ||
| 39 | * (2 bytes) LogEntryType entry_type; | ||
| 40 | * (? bytes) select(entry_type) { | ||
| 41 | * case x509_entry: ASN.1Cert; | ||
| 42 | * case precert_entry: PreCert; | ||
| 43 | * } signed_entry; | ||
| 44 | * (2 bytes + sct->ext_len) CtExtensions extensions; | ||
| 45 | * } | ||
| 46 | */ | ||
| 47 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET) | ||
| 48 | return 0; | ||
| 49 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL) | ||
| 50 | return 0; | ||
| 51 | |||
| 52 | p = tmpbuf; | ||
| 53 | *p++ = sct->version; | ||
| 54 | *p++ = SIGNATURE_TYPE_CERT_TIMESTAMP; | ||
| 55 | l2n8(sct->timestamp, p); | ||
| 56 | s2n(sct->entry_type, p); | ||
| 57 | |||
| 58 | if (!EVP_DigestUpdate(ctx, tmpbuf, p - tmpbuf)) | ||
| 59 | return 0; | ||
| 60 | |||
| 61 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_X509) { | ||
| 62 | der = sctx->certder; | ||
| 63 | derlen = sctx->certderlen; | ||
| 64 | } else { | ||
| 65 | if (!EVP_DigestUpdate(ctx, sctx->ihash, sctx->ihashlen)) | ||
| 66 | return 0; | ||
| 67 | der = sctx->preder; | ||
| 68 | derlen = sctx->prederlen; | ||
| 69 | } | ||
| 70 | |||
| 71 | /* If no encoding available, fatal error */ | ||
| 72 | if (der == NULL) | ||
| 73 | return 0; | ||
| 74 | |||
| 75 | /* Include length first */ | ||
| 76 | p = tmpbuf; | ||
| 77 | l2n3(derlen, p); | ||
| 78 | |||
| 79 | if (!EVP_DigestUpdate(ctx, tmpbuf, 3)) | ||
| 80 | return 0; | ||
| 81 | if (!EVP_DigestUpdate(ctx, der, derlen)) | ||
| 82 | return 0; | ||
| 83 | |||
| 84 | /* Add any extensions */ | ||
| 85 | p = tmpbuf; | ||
| 86 | s2n(sct->ext_len, p); | ||
| 87 | if (!EVP_DigestUpdate(ctx, tmpbuf, 2)) | ||
| 88 | return 0; | ||
| 89 | |||
| 90 | if (sct->ext_len && !EVP_DigestUpdate(ctx, sct->ext, sct->ext_len)) | ||
| 91 | return 0; | ||
| 92 | |||
| 93 | return 1; | ||
| 94 | } | ||
| 95 | |||
| 96 | int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct) | ||
| 97 | { | ||
| 98 | EVP_MD_CTX *ctx = NULL; | ||
| 99 | int ret = 0; | ||
| 100 | |||
| 101 | if (!SCT_is_complete(sct) || sctx->pkey == NULL || | ||
| 102 | sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET || | ||
| 103 | (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL)) { | ||
| 104 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_NOT_SET); | ||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | if (sct->version != SCT_VERSION_V1) { | ||
| 108 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_UNSUPPORTED_VERSION); | ||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | if (sct->log_id_len != sctx->pkeyhashlen || | ||
| 112 | memcmp(sct->log_id, sctx->pkeyhash, sctx->pkeyhashlen) != 0) { | ||
| 113 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_LOG_ID_MISMATCH); | ||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | if (sct->timestamp > sctx->epoch_time_in_ms) { | ||
| 117 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_FUTURE_TIMESTAMP); | ||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | ctx = EVP_MD_CTX_new(); | ||
| 122 | if (ctx == NULL) | ||
| 123 | goto end; | ||
| 124 | |||
| 125 | if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey)) | ||
| 126 | goto end; | ||
| 127 | |||
| 128 | if (!sct_ctx_update(ctx, sctx, sct)) | ||
| 129 | goto end; | ||
| 130 | |||
| 131 | /* Verify signature */ | ||
| 132 | ret = EVP_DigestVerifyFinal(ctx, sct->sig, sct->sig_len); | ||
| 133 | /* If ret < 0 some other error: fall through without setting error */ | ||
| 134 | if (ret == 0) | ||
| 135 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_INVALID_SIGNATURE); | ||
| 136 | |||
| 137 | end: | ||
| 138 | EVP_MD_CTX_free(ctx); | ||
| 139 | return ret; | ||
| 140 | } | ||
| diff --git a/src/lib/libcrypto/ct/ct_x509v3.c b/src/lib/libcrypto/ct/ct_x509v3.c new file mode 100644 index 0000000000..19c2a852d2 --- /dev/null +++ b/src/lib/libcrypto/ct/ct_x509v3.c | |||
| @@ -0,0 +1,104 @@ | |||
| 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 | #ifdef OPENSSL_NO_CT | ||
| 11 | # error "CT is disabled" | ||
| 12 | #endif | ||
| 13 | |||
| 14 | #include "ct_local.h" | ||
| 15 | |||
| 16 | static char *i2s_poison(const X509V3_EXT_METHOD *method, void *val) | ||
| 17 | { | ||
| 18 | return OPENSSL_strdup("NULL"); | ||
| 19 | } | ||
| 20 | |||
| 21 | static void *s2i_poison(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str) | ||
| 22 | { | ||
| 23 | return ASN1_NULL_new(); | ||
| 24 | } | ||
| 25 | |||
| 26 | static int i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list, | ||
| 27 | BIO *out, int indent) | ||
| 28 | { | ||
| 29 | SCT_LIST_print(sct_list, out, indent, "\n", NULL); | ||
| 30 | return 1; | ||
| 31 | } | ||
| 32 | |||
| 33 | static int set_sct_list_source(STACK_OF(SCT) *s, sct_source_t source) | ||
| 34 | { | ||
| 35 | if (s != NULL) { | ||
| 36 | int i; | ||
| 37 | |||
| 38 | for (i = 0; i < sk_SCT_num(s); i++) { | ||
| 39 | int res = SCT_set_source(sk_SCT_value(s, i), source); | ||
| 40 | |||
| 41 | if (res != 1) { | ||
| 42 | return 0; | ||
| 43 | } | ||
| 44 | } | ||
| 45 | } | ||
| 46 | return 1; | ||
| 47 | } | ||
| 48 | |||
| 49 | static STACK_OF(SCT) *x509_ext_d2i_SCT_LIST(STACK_OF(SCT) **a, | ||
| 50 | const unsigned char **pp, | ||
| 51 | long len) | ||
| 52 | { | ||
| 53 | STACK_OF(SCT) *s = d2i_SCT_LIST(a, pp, len); | ||
| 54 | |||
| 55 | if (set_sct_list_source(s, SCT_SOURCE_X509V3_EXTENSION) != 1) { | ||
| 56 | SCT_LIST_free(s); | ||
| 57 | *a = NULL; | ||
| 58 | return NULL; | ||
| 59 | } | ||
| 60 | return s; | ||
| 61 | } | ||
| 62 | |||
| 63 | static STACK_OF(SCT) *ocsp_ext_d2i_SCT_LIST(STACK_OF(SCT) **a, | ||
| 64 | const unsigned char **pp, | ||
| 65 | long len) | ||
| 66 | { | ||
| 67 | STACK_OF(SCT) *s = d2i_SCT_LIST(a, pp, len); | ||
| 68 | |||
| 69 | if (set_sct_list_source(s, SCT_SOURCE_OCSP_STAPLED_RESPONSE) != 1) { | ||
| 70 | SCT_LIST_free(s); | ||
| 71 | *a = NULL; | ||
| 72 | return NULL; | ||
| 73 | } | ||
| 74 | return s; | ||
| 75 | } | ||
| 76 | |||
| 77 | /* Handlers for X509v3/OCSP Certificate Transparency extensions */ | ||
| 78 | const X509V3_EXT_METHOD v3_ct_scts[3] = { | ||
| 79 | /* X509v3 extension in certificates that contains SCTs */ | ||
| 80 | { NID_ct_precert_scts, 0, NULL, | ||
| 81 | NULL, (X509V3_EXT_FREE)SCT_LIST_free, | ||
| 82 | (X509V3_EXT_D2I)x509_ext_d2i_SCT_LIST, (X509V3_EXT_I2D)i2d_SCT_LIST, | ||
| 83 | NULL, NULL, | ||
| 84 | NULL, NULL, | ||
| 85 | (X509V3_EXT_I2R)i2r_SCT_LIST, NULL, | ||
| 86 | NULL }, | ||
| 87 | |||
| 88 | /* X509v3 extension to mark a certificate as a pre-certificate */ | ||
| 89 | { NID_ct_precert_poison, 0, ASN1_ITEM_ref(ASN1_NULL), | ||
| 90 | NULL, NULL, NULL, NULL, | ||
| 91 | i2s_poison, s2i_poison, | ||
| 92 | NULL, NULL, | ||
| 93 | NULL, NULL, | ||
| 94 | NULL }, | ||
| 95 | |||
| 96 | /* OCSP extension that contains SCTs */ | ||
| 97 | { NID_ct_cert_scts, 0, NULL, | ||
| 98 | 0, (X509V3_EXT_FREE)SCT_LIST_free, | ||
| 99 | (X509V3_EXT_D2I)ocsp_ext_d2i_SCT_LIST, (X509V3_EXT_I2D)i2d_SCT_LIST, | ||
| 100 | NULL, NULL, | ||
| 101 | NULL, NULL, | ||
| 102 | (X509V3_EXT_I2R)i2r_SCT_LIST, NULL, | ||
| 103 | NULL }, | ||
| 104 | }; | ||
| diff --git a/src/lib/libcrypto/ct/cterr.h b/src/lib/libcrypto/ct/cterr.h new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/src/lib/libcrypto/ct/cterr.h | |||
