diff options
-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 | |||