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