/* * Written by Rob Stradling (rob@comodo.com) and Stephen Henson * (steve@openssl.org) for the OpenSSL project 2014. */ /* ==================================================================== * Copyright (c) 2014 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * licensing@OpenSSL.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ #include #include #include #include #include /* * TODO(robpercival): These macros are getting duplicated all over the place. * Is there a single place they should be defined for re-use? * Also, is there a good reason they aren't functions? */ #define n2s(c,s) ((s=(((unsigned int)((c)[0]))<<8) | \ (((unsigned int)((c)[1])))), \ c+=2) /* * Decodes the base64 string |in| into |out|. * A new string will be malloc'd and assigned to |out|. This will be owned by * the caller. Do not provide a pre-allocated string in |out|. */ static int ct_base64_decode(const char *in, unsigned char **out) { size_t inlen = strlen(in); int outlen; unsigned char *outbuf = NULL; if (inlen == 0) { *out = NULL; return 0; } outlen = (inlen / 4) * 3; outbuf = OPENSSL_malloc(outlen); if (outbuf == NULL) { CTerr(CT_F_CT_BASE64_DECODE, ERR_R_MALLOC_FAILURE); goto err; } outlen = EVP_DecodeBlock(outbuf, (unsigned char *)in, inlen); if (outlen < 0) { CTerr(CT_F_CT_BASE64_DECODE, CT_R_BASE64_DECODE_ERROR); goto err; } *out = outbuf; return outlen; err: OPENSSL_free(outbuf); return -1; } SCT *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) { SCT *sct = SCT_new(); unsigned char *dec = NULL; int declen; if (sct == NULL) { CTerr(CT_F_SCT_NEW_FROM_BASE64, ERR_R_MALLOC_FAILURE); return NULL; } /* * RFC6962 section 4.1 says we "MUST NOT expect this to be 0", but we * can only construct SCT versions that have been defined. */ if (!SCT_set_version(sct, version)) { CTerr(CT_F_SCT_NEW_FROM_BASE64, CT_R_SCT_UNSUPPORTED_VERSION); goto err; } declen = ct_base64_decode(logid_base64, &dec); if (declen < 0) { CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); goto err; } if (!SCT_set0_log_id(sct, dec, declen)) goto err; dec = NULL; declen = ct_base64_decode(extensions_base64, &dec); if (declen < 0) { CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); goto err; } SCT_set0_extensions(sct, dec, declen); dec = NULL; declen = ct_base64_decode(signature_base64, &dec); if (declen < 0) { CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); goto err; } if (o2i_SCT_signature(sct, (const unsigned char **)&dec, declen) <= 0) goto err; OPENSSL_free(dec); dec = NULL; SCT_set_timestamp(sct, timestamp); if (!SCT_set_log_entry_type(sct, entry_type)) goto err; return sct; err: OPENSSL_free(dec); SCT_free(sct); return NULL; } CTLOG *CTLOG_new_from_base64(const char *pkey_base64, const char *name) { unsigned char *pkey_der = NULL; int pkey_der_len = ct_base64_decode(pkey_base64, &pkey_der); const unsigned char *p; EVP_PKEY *pkey = NULL; CTLOG *log = NULL; if (pkey_der_len <= 0) { CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY); return NULL; } p = pkey_der; pkey = d2i_PUBKEY(NULL, &p, pkey_der_len); OPENSSL_free(pkey_der); if (pkey == NULL) { CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY); return NULL; } log = CTLOG_new(pkey, name); if (log == NULL) { EVP_PKEY_free(pkey); return NULL; } return log; }