Fixes memory leaks in CT code
[openssl.git] / crypto / ct / ct_sct.c
index 62cadc974368a53808438d905718de9107418449..2b7211d7ea42f42cb34e00c649bddc7753839fe6 100644 (file)
@@ -70,7 +70,7 @@
 
 SCT *SCT_new(void)
 {
-    SCT *sct = OPENSSL_zalloc(sizeof(SCT));
+    SCT *sct = OPENSSL_zalloc(sizeof(*sct));
 
     if (sct == NULL) {
         CTerr(CT_F_SCT_NEW, ERR_R_MALLOC_FAILURE);
@@ -335,8 +335,7 @@ CTLOG *SCT_get0_log(const SCT *sct)
 
 int SCT_set0_log(SCT *sct, const CTLOG_STORE *ct_logs)
 {
-    sct->log =
-            CTLOG_STORE_get0_log_by_id(ct_logs, sct->log_id, sct->log_id_len);
+    sct->log = CTLOG_STORE_get0_log_by_id(ct_logs, sct->log_id, sct->log_id_len);
 
     return sct->log != NULL;
 }
@@ -357,3 +356,94 @@ int SCT_LIST_set0_logs(STACK_OF(SCT) *sct_list, const CTLOG_STORE *ct_logs)
 
     return sct_logs_found;
 }
+
+sct_validation_status_t SCT_get_validation_status(const SCT *sct)
+{
+    return sct->validation_status;
+}
+
+int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx)
+{
+    int is_sct_valid = -1;
+    SCT_CTX *sctx = NULL;
+    X509_PUBKEY *pub = NULL, *log_pkey = NULL;
+
+    switch (sct->version) {
+    case SCT_VERSION_V1:
+        if (sct->log == NULL)
+            sct->log = CTLOG_STORE_get0_log_by_id(ctx->log_store,
+                                                  sct->log_id,
+                                                  CT_V1_HASHLEN);
+        break;
+    default:
+        sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_VERSION;
+        goto end;
+    }
+
+    if (sct->log == NULL) {
+        sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_LOG;
+        goto end;
+    }
+
+    sctx = SCT_CTX_new();
+    if (sctx == NULL)
+        goto err;
+
+    if (X509_PUBKEY_set(&log_pkey, CTLOG_get0_public_key(sct->log)) != 1)
+        goto err;
+    if (SCT_CTX_set1_pubkey(sctx, log_pkey) != 1)
+        goto err;
+
+    if (SCT_get_log_entry_type(sct) == CT_LOG_ENTRY_TYPE_PRECERT) {
+        EVP_PKEY *issuer_pkey;
+
+        if (ctx->issuer == NULL) {
+            sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED;
+            goto end;
+        }
+
+        issuer_pkey = X509_get0_pubkey(ctx->issuer);
+
+        if (X509_PUBKEY_set(&pub, issuer_pkey) != 1)
+            goto err;
+        if (SCT_CTX_set1_issuer_pubkey(sctx, pub) != 1)
+            goto err;
+    }
+
+    if (SCT_CTX_set1_cert(sctx, ctx->cert, NULL) != 1)
+        goto err;
+
+    sct->validation_status = SCT_verify(sctx, sct) == 1 ?
+            SCT_VALIDATION_STATUS_VALID : SCT_VALIDATION_STATUS_INVALID;
+
+end:
+    is_sct_valid = sct->validation_status == SCT_VALIDATION_STATUS_VALID;
+err:
+    X509_PUBKEY_free(pub);
+    X509_PUBKEY_free(log_pkey);
+    SCT_CTX_free(sctx);
+
+    return is_sct_valid;
+}
+
+int SCT_LIST_validate(const STACK_OF(SCT) *scts, CT_POLICY_EVAL_CTX *ctx)
+{
+    int are_scts_valid = 1;
+    int sct_count = scts != NULL ? sk_SCT_num(scts) : 0;
+    int i;
+
+    for (i = 0; i < sct_count; ++i) {
+        int is_sct_valid = -1;
+        SCT *sct = sk_SCT_value(scts, i);
+
+        if (sct == NULL)
+            continue;
+
+        is_sct_valid = SCT_validate(sct, ctx);
+        if (is_sct_valid < 0)
+            return is_sct_valid;
+        are_scts_valid &= is_sct_valid;
+    }
+
+    return are_scts_valid;
+}