diff options
Diffstat (limited to 'src/lib/libcrypto/ct/ct_vfy.c')
-rw-r--r-- | src/lib/libcrypto/ct/ct_vfy.c | 222 |
1 files changed, 112 insertions, 110 deletions
diff --git a/src/lib/libcrypto/ct/ct_vfy.c b/src/lib/libcrypto/ct/ct_vfy.c index 74fd34f415..74642a9304 100644 --- a/src/lib/libcrypto/ct/ct_vfy.c +++ b/src/lib/libcrypto/ct/ct_vfy.c | |||
@@ -17,124 +17,126 @@ | |||
17 | #include "ct_local.h" | 17 | #include "ct_local.h" |
18 | 18 | ||
19 | typedef enum sct_signature_type_t { | 19 | typedef enum sct_signature_type_t { |
20 | SIGNATURE_TYPE_NOT_SET = -1, | 20 | SIGNATURE_TYPE_NOT_SET = -1, |
21 | SIGNATURE_TYPE_CERT_TIMESTAMP, | 21 | SIGNATURE_TYPE_CERT_TIMESTAMP, |
22 | SIGNATURE_TYPE_TREE_HASH | 22 | SIGNATURE_TYPE_TREE_HASH |
23 | } SCT_SIGNATURE_TYPE; | 23 | } SCT_SIGNATURE_TYPE; |
24 | 24 | ||
25 | /* | 25 | /* |
26 | * Update encoding for SCT signature verification/generation to supplied | 26 | * Update encoding for SCT signature verification/generation to supplied |
27 | * EVP_MD_CTX. | 27 | * EVP_MD_CTX. |
28 | */ | 28 | */ |
29 | static int sct_ctx_update(EVP_MD_CTX *ctx, const SCT_CTX *sctx, const SCT *sct) | 29 | static int |
30 | sct_ctx_update(EVP_MD_CTX *ctx, const SCT_CTX *sctx, const SCT *sct) | ||
30 | { | 31 | { |
31 | unsigned char tmpbuf[12]; | 32 | unsigned char tmpbuf[12]; |
32 | unsigned char *p, *der; | 33 | unsigned char *p, *der; |
33 | size_t derlen; | 34 | size_t derlen; |
34 | /*+ | 35 | /*+ |
35 | * digitally-signed struct { | 36 | * digitally-signed struct { |
36 | * (1 byte) Version sct_version; | 37 | * (1 byte) Version sct_version; |
37 | * (1 byte) SignatureType signature_type = certificate_timestamp; | 38 | * (1 byte) SignatureType signature_type = certificate_timestamp; |
38 | * (8 bytes) uint64 timestamp; | 39 | * (8 bytes) uint64 timestamp; |
39 | * (2 bytes) LogEntryType entry_type; | 40 | * (2 bytes) LogEntryType entry_type; |
40 | * (? bytes) select(entry_type) { | 41 | * (? bytes) select(entry_type) { |
41 | * case x509_entry: ASN.1Cert; | 42 | * case x509_entry: ASN.1Cert; |
42 | * case precert_entry: PreCert; | 43 | * case precert_entry: PreCert; |
43 | * } signed_entry; | 44 | * } signed_entry; |
44 | * (2 bytes + sct->ext_len) CtExtensions extensions; | 45 | * (2 bytes + sct->ext_len) CtExtensions extensions; |
45 | * } | 46 | * } |
46 | */ | 47 | */ |
47 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET) | 48 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET) |
48 | return 0; | 49 | return 0; |
49 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL) | 50 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL) |
50 | return 0; | 51 | return 0; |
51 | 52 | ||
52 | p = tmpbuf; | 53 | p = tmpbuf; |
53 | *p++ = sct->version; | 54 | *p++ = sct->version; |
54 | *p++ = SIGNATURE_TYPE_CERT_TIMESTAMP; | 55 | *p++ = SIGNATURE_TYPE_CERT_TIMESTAMP; |
55 | l2n8(sct->timestamp, p); | 56 | l2n8(sct->timestamp, p); |
56 | s2n(sct->entry_type, p); | 57 | s2n(sct->entry_type, p); |
57 | 58 | ||
58 | if (!EVP_DigestUpdate(ctx, tmpbuf, p - tmpbuf)) | 59 | if (!EVP_DigestUpdate(ctx, tmpbuf, p - tmpbuf)) |
59 | return 0; | 60 | return 0; |
60 | 61 | ||
61 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_X509) { | 62 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_X509) { |
62 | der = sctx->certder; | 63 | der = sctx->certder; |
63 | derlen = sctx->certderlen; | 64 | derlen = sctx->certderlen; |
64 | } else { | 65 | } else { |
65 | if (!EVP_DigestUpdate(ctx, sctx->ihash, sctx->ihashlen)) | 66 | if (!EVP_DigestUpdate(ctx, sctx->ihash, sctx->ihashlen)) |
66 | return 0; | 67 | return 0; |
67 | der = sctx->preder; | 68 | der = sctx->preder; |
68 | derlen = sctx->prederlen; | 69 | derlen = sctx->prederlen; |
69 | } | 70 | } |
70 | 71 | ||
71 | /* If no encoding available, fatal error */ | 72 | /* If no encoding available, fatal error */ |
72 | if (der == NULL) | 73 | if (der == NULL) |
73 | return 0; | 74 | return 0; |
74 | 75 | ||
75 | /* Include length first */ | 76 | /* Include length first */ |
76 | p = tmpbuf; | 77 | p = tmpbuf; |
77 | l2n3(derlen, p); | 78 | l2n3(derlen, p); |
78 | 79 | ||
79 | if (!EVP_DigestUpdate(ctx, tmpbuf, 3)) | 80 | if (!EVP_DigestUpdate(ctx, tmpbuf, 3)) |
80 | return 0; | 81 | return 0; |
81 | if (!EVP_DigestUpdate(ctx, der, derlen)) | 82 | if (!EVP_DigestUpdate(ctx, der, derlen)) |
82 | return 0; | 83 | return 0; |
83 | 84 | ||
84 | /* Add any extensions */ | 85 | /* Add any extensions */ |
85 | p = tmpbuf; | 86 | p = tmpbuf; |
86 | s2n(sct->ext_len, p); | 87 | s2n(sct->ext_len, p); |
87 | if (!EVP_DigestUpdate(ctx, tmpbuf, 2)) | 88 | if (!EVP_DigestUpdate(ctx, tmpbuf, 2)) |
88 | return 0; | 89 | return 0; |
89 | 90 | ||
90 | if (sct->ext_len && !EVP_DigestUpdate(ctx, sct->ext, sct->ext_len)) | 91 | if (sct->ext_len && !EVP_DigestUpdate(ctx, sct->ext, sct->ext_len)) |
91 | return 0; | 92 | return 0; |
92 | 93 | ||
93 | return 1; | 94 | return 1; |
94 | } | 95 | } |
95 | 96 | ||
96 | int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct) | 97 | int |
98 | SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct) | ||
97 | { | 99 | { |
98 | EVP_MD_CTX *ctx = NULL; | 100 | EVP_MD_CTX *ctx = NULL; |
99 | int ret = 0; | 101 | int ret = 0; |
100 | 102 | ||
101 | if (!SCT_is_complete(sct) || sctx->pkey == NULL || | 103 | if (!SCT_is_complete(sct) || sctx->pkey == NULL || |
102 | sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET || | 104 | sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET || |
103 | (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL)) { | 105 | (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL)) { |
104 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_NOT_SET); | 106 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_NOT_SET); |
105 | return 0; | 107 | return 0; |
106 | } | 108 | } |
107 | if (sct->version != SCT_VERSION_V1) { | 109 | if (sct->version != SCT_VERSION_V1) { |
108 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_UNSUPPORTED_VERSION); | 110 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_UNSUPPORTED_VERSION); |
109 | return 0; | 111 | return 0; |
110 | } | 112 | } |
111 | if (sct->log_id_len != sctx->pkeyhashlen || | 113 | if (sct->log_id_len != sctx->pkeyhashlen || |
112 | memcmp(sct->log_id, sctx->pkeyhash, sctx->pkeyhashlen) != 0) { | 114 | memcmp(sct->log_id, sctx->pkeyhash, sctx->pkeyhashlen) != 0) { |
113 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_LOG_ID_MISMATCH); | 115 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_LOG_ID_MISMATCH); |
114 | return 0; | 116 | return 0; |
115 | } | 117 | } |
116 | if (sct->timestamp > sctx->epoch_time_in_ms) { | 118 | if (sct->timestamp > sctx->epoch_time_in_ms) { |
117 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_FUTURE_TIMESTAMP); | 119 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_FUTURE_TIMESTAMP); |
118 | return 0; | 120 | return 0; |
119 | } | 121 | } |
120 | 122 | ||
121 | ctx = EVP_MD_CTX_new(); | 123 | ctx = EVP_MD_CTX_new(); |
122 | if (ctx == NULL) | 124 | if (ctx == NULL) |
123 | goto end; | 125 | goto end; |
124 | 126 | ||
125 | if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey)) | 127 | if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey)) |
126 | goto end; | 128 | goto end; |
127 | 129 | ||
128 | if (!sct_ctx_update(ctx, sctx, sct)) | 130 | if (!sct_ctx_update(ctx, sctx, sct)) |
129 | goto end; | 131 | goto end; |
130 | 132 | ||
131 | /* Verify signature */ | 133 | /* Verify signature */ |
132 | ret = EVP_DigestVerifyFinal(ctx, sct->sig, sct->sig_len); | 134 | ret = EVP_DigestVerifyFinal(ctx, sct->sig, sct->sig_len); |
133 | /* If ret < 0 some other error: fall through without setting error */ | 135 | /* If ret < 0 some other error: fall through without setting error */ |
134 | if (ret == 0) | 136 | if (ret == 0) |
135 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_INVALID_SIGNATURE); | 137 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_INVALID_SIGNATURE); |
136 | 138 | ||
137 | end: | 139 | end: |
138 | EVP_MD_CTX_free(ctx); | 140 | EVP_MD_CTX_free(ctx); |
139 | return ret; | 141 | return ret; |
140 | } | 142 | } |