/* * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * * http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include #include #include #include #include static int test_x509_crl_reason(void) { uint8_t buf[256]; uint8_t *p = buf; const uint8_t *cp = buf; size_t len = 0; int reason; int i; for (i = 0; i < 11; i++) { if (x509_crl_reason_to_der(i, &p, &len) != 1) { error_print(); return -1; } format_bytes(stderr, 0, 4, "", buf, len); } for (i = 0; i < 11; i++) { if (x509_crl_reason_from_der(&reason, &cp, &len) != 1 || asn1_check(reason == i) != 1) { error_print(); return -1; } format_print(stderr, 0, 4, "%s (%d)\n", x509_crl_reason_name(reason), reason); } (void)asn1_length_is_zero(len); printf("%s() ok\n", __FUNCTION__); return 1; } static int test_x509_crl_entry_ext(void) { int exts[] = { OID_ce_crl_reasons, OID_ce_invalidity_date, OID_ce_certificate_issuer, }; uint8_t buf[256]; uint8_t *p = buf; const uint8_t *cp = buf; size_t len = 0; int oid; int i; for (i = 0; i < sizeof(exts)/sizeof(exts[0]); i++) { if (x509_crl_entry_ext_id_to_der(exts[i], &p, &len) != 1) { error_print(); return -1; } format_bytes(stderr, 0, 4, "", buf, len); } for (i = 0; i < sizeof(exts)/sizeof(exts[0]); i++) { if (x509_crl_entry_ext_id_from_der(&oid, &cp, &len) != 1 || asn1_check(oid == exts[i]) != 1) { error_print(); return -1; } format_print(stderr, 0, 4, "%s\n", x509_crl_entry_ext_id_name(oid)); } (void)asn1_length_is_zero(len); printf("%s() ok\n", __FUNCTION__); return 1; } static int test_vector_gen_uri_as_general_names(void) { const char *uri = "http://www.example.com/path"; uint8_t buf[256]; uint8_t *p; const uint8_t *cp; size_t len; const uint8_t *d; size_t dlen; size_t i; cp = p = buf; len = 0; if (x509_uri_as_general_names_to_der(uri, strlen(uri), &p, &len) != 1 || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 || asn1_length_is_zero(len) != 1) { error_print(); return -1; } printf("// generated by %s()\n", __FUNCTION__); printf("const uint8_t cert_issuer[] = {\n\t"); for (i = 0; i < dlen; i++) { printf("0x%02x,", d[i]); if ((i + 1) % 8 == 0) printf("\n\t"); } printf("\n};\n"); return 1; } static int test_x509_crl_entry_exts(void) { // generated by test_vector_gen_uri_as_general_names() const uint8_t cert_issuer[] = { 0x86,0x1b,0x68,0x74,0x74,0x70,0x3a,0x2f, 0x2f,0x77,0x77,0x77,0x2e,0x65,0x78,0x61, 0x6d,0x70,0x6c,0x65,0x2e,0x63,0x6f,0x6d, 0x2f,0x70,0x61,0x74,0x68, }; struct { int reason; time_t invalid_date; const uint8_t *cert_issuer; size_t cert_issuer_len; } tests[] = { { X509_cr_key_compromise, -1, NULL, 0 }, { -1, time(NULL), NULL, 0 }, { -1, -1, cert_issuer, sizeof(cert_issuer) }, { X509_cr_key_compromise, time(NULL), NULL, 0 }, { X509_cr_key_compromise, time(NULL), cert_issuer, sizeof(cert_issuer) }, }; uint8_t buf[1024]; uint8_t *p; const uint8_t *cp; size_t len; size_t i; int reason; time_t invalid_date; const uint8_t *issuer; size_t issuer_len; cp = p = buf; len = 0; if (x509_crl_entry_exts_to_der(-1, -1, NULL, 0, &p, &len) != 0) { error_print(); return -1; } for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { if (x509_crl_entry_exts_to_der( tests[i].reason, tests[i].invalid_date, tests[i].cert_issuer, tests[i].cert_issuer_len, &p, &len) != 1) { error_print(); return -1; } //printf("%s %d: test %zu passed\n", __FILE__, __LINE__, i); if (len > sizeof(buf)) { error_print(); return -1; } } { size_t left = len; const uint8_t *d; size_t dlen; cp = buf; while (left) { if (asn1_sequence_from_der(&d, &dlen, &cp, &left) != 1) { error_print(); return -1; } x509_crl_entry_exts_print(stderr, 0, 0, "CRLEntryExtensions", d, dlen); if (x509_crl_entry_exts_check(d, dlen) != 1) { error_print(); return -1; } } } cp = p = buf; for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { if (x509_crl_entry_exts_from_der(&reason, &invalid_date, &issuer, &issuer_len, &cp, &len) != 1) { error_print(); return -1; } if (reason != tests[i].reason) { error_print(); return -1; } if (invalid_date != tests[i].invalid_date) { error_print(); return -1; } if (issuer_len != tests[i].cert_issuer_len || memcmp(issuer, tests[i].cert_issuer, issuer_len) != 0) { error_print(); return -1; } //printf("%s %d: test %zu passed\n", __FILE__, __LINE__, i); } if (len != 0) { error_print(); return -1; } printf("%s() ok\n", __FUNCTION__); return 1; } static int test_x509_revoked_cert(void) { uint8_t serial_buf[16] = { 0x01,0x02,0x00 }; time_t revoke_date = time(NULL); int reason = X509_cr_key_compromise; time_t invalid_date = revoke_date; // generated by test_vector_gen_uri_as_general_names() const uint8_t cert_issuer_buf[] = { 0x86,0x1b,0x68,0x74,0x74,0x70,0x3a,0x2f, 0x2f,0x77,0x77,0x77,0x2e,0x65,0x78,0x61, 0x6d,0x70,0x6c,0x65,0x2e,0x63,0x6f,0x6d, 0x2f,0x70,0x61,0x74,0x68, }; const uint8_t *serial; size_t serial_len; const uint8_t *cert_issuer; size_t cert_issuer_len; uint8_t buf[512]; uint8_t *p; const uint8_t *cp; size_t len = 0; const uint8_t *d; size_t dlen; cp = p = buf; len = 0; if (x509_revoked_cert_to_der_ex(serial_buf, sizeof(serial_buf), revoke_date, reason, invalid_date, cert_issuer_buf, sizeof(cert_issuer_buf), &p, &len) != 1 || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 || asn1_length_is_zero(len) != 1) { error_print(); return -1; } x509_revoked_cert_print(stderr, 0, 0, "RevokedCertificate", d, dlen); cp = p = buf; len = 0; if (x509_revoked_cert_to_der_ex(serial_buf, sizeof(serial_buf), revoke_date, reason, invalid_date, cert_issuer_buf, sizeof(cert_issuer_buf), &p, &len) != 1 || x509_revoked_cert_from_der_ex(&serial, &serial_len, &revoke_date, &reason, &invalid_date, &cert_issuer, &cert_issuer_len, &cp, &len) != 1 || asn1_length_is_zero(len) != 1) { error_print(); return -1; } printf("%s() ok\n", __FUNCTION__); return 1; } static int test_x509_crl_ext_id(void) { int crl_ext_oids[] = { OID_ce_authority_key_identifier, OID_ce_issuer_alt_name, OID_ce_crl_number, OID_ce_delta_crl_indicator, OID_ce_issuing_distribution_point, OID_ce_freshest_crl, OID_pe_authority_info_access, }; int oid; uint8_t buf[512]; uint8_t *p; const uint8_t *cp; size_t len; size_t i; cp = p = buf; len = 0; for (i = 0; i < sizeof(crl_ext_oids)/sizeof(crl_ext_oids[0]); i++) { if (x509_crl_ext_id_to_der(crl_ext_oids[i], &p, &len) != 1) { error_print(); return -1; } format_bytes(stderr, 0, 0, "", buf, len); } for (i = 0; i < sizeof(crl_ext_oids)/sizeof(crl_ext_oids[0]); i++) { if (x509_crl_ext_id_from_der(&oid, &cp, &len) != 1) { error_print(); return -1; } printf(" %s\n", x509_crl_ext_id_name(oid)); } if (len) { error_print(); return -1; } printf("%s() ok\n", __FUNCTION__); return 1; } static int test_x509_issuing_distribution_point(void) { char *dist_point_uri = "http://www.example.com/crl.crl"; int reason_flags = X509_RF_KEY_COMPROMISE|X509_RF_CA_COMPROMISE; uint8_t buf[512]; uint8_t *p = buf; const uint8_t *cp = buf; size_t len = 0; const uint8_t *d; size_t dlen; if (x509_issuing_distribution_point_to_der( dist_point_uri, strlen(dist_point_uri), ASN1_TRUE, ASN1_TRUE, reason_flags, ASN1_TRUE, ASN1_TRUE, &p, &len) != 1) { error_print(); return -1; } if (asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 || asn1_length_is_zero(len) != 1) { error_print(); return -1; } x509_issuing_distribution_point_print(stderr, 0, 0, "IssuingDistributionPoint", d, dlen); printf("%s() ok\n", __FUNCTION__); return 1; } static int test_x509_issuing_distribution_point_from_der(void) { char *uri = "http://www.example.com/crl.crl"; int flags = X509_RF_KEY_COMPROMISE|X509_RF_CA_COMPROMISE; uint8_t buf[512]; uint8_t *p = buf; const uint8_t *cp = buf; size_t len = 0; int dist_point_choice; const uint8_t *dist_point; size_t dist_point_len; int only_contains_user_certs; int only_contains_ca_certs; int only_some_reasons; int indirect_crl; int only_contains_attr_certs; if (x509_issuing_distribution_point_to_der( uri, strlen(uri), ASN1_TRUE, ASN1_FALSE, flags, -1, ASN1_FALSE, &p, &len) != 1) { error_print(); return -1; } if (x509_issuing_distribution_point_from_der( &dist_point_choice, &dist_point, &dist_point_len, &only_contains_user_certs, &only_contains_ca_certs, &only_some_reasons, &indirect_crl, &only_contains_attr_certs, &cp, &len) != 1 || asn1_length_is_zero(len) != 1) { error_print(); return -1; } printf("%s() ok\n", __FUNCTION__); return 1; } static int test_x509_crl_exts(void) { uint8_t exts[1024]; size_t extslen = 0; uint8_t key_id[32]; uint8_t issuer[128]; size_t issuer_len = 0; uint8_t serial[20]; char *http_uri = "http://www.example.com/crl.crl"; char *ldap_uri = "ldap://www.example.com/ldap"; char *ca_issuers_uri = "http://www.example.com/ca.crt"; char *ocsp_uri = "http://www.example.com/ocsp"; char *dist_point_uri = "http://www.example.com/crl.crl"; int reason_flags = X509_RF_KEY_COMPROMISE|X509_RF_CA_COMPROMISE; if (rand_bytes(key_id, sizeof(key_id)) != 1 || x509_general_names_add_uniform_resource_identifier(issuer, &issuer_len, sizeof(issuer), "http://www.example.com") != 1 || rand_bytes(serial, sizeof(serial)) != 1) { error_print(); return -1; } if (x509_crl_exts_add_authority_key_identifier(exts, &extslen, sizeof(exts), -1, key_id, sizeof(key_id), issuer, issuer_len, serial, sizeof(serial)) != 1 || x509_crl_exts_add_issuer_alt_name(exts, &extslen, sizeof(exts), X509_non_critical, issuer, issuer_len) != 1 || x509_crl_exts_add_crl_number(exts, &extslen, sizeof(exts), X509_non_critical, 112) != 1 || x509_crl_exts_add_delta_crl_indicator(exts, &extslen, sizeof(exts), X509_critical, 113) != 1 || x509_crl_exts_add_issuing_distribution_point(exts, &extslen, sizeof(exts), X509_critical, dist_point_uri, strlen(dist_point_uri), ASN1_FALSE, ASN1_FALSE, reason_flags, ASN1_FALSE, ASN1_FALSE) != 1 || x509_crl_exts_add_freshest_crl(exts, &extslen, sizeof(exts), X509_non_critical, http_uri, strlen(http_uri), ldap_uri, strlen(ldap_uri)) != 1 || x509_crl_exts_add_authority_info_acess(exts, &extslen, sizeof(exts), X509_non_critical, ca_issuers_uri, strlen(ca_issuers_uri), ocsp_uri, strlen(ocsp_uri)) != 1 ) { error_print(); return -1; } x509_crl_exts_print(stderr, 0, 0, "CRLExtensions", exts, extslen); return 1; } static int test_x509_cert_revoke(void) { printf("%s() ok\n", __FUNCTION__); return 1; } /* http://mscrl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl http://crl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl http://crl3.digicert.com/Omniroot2025.crl */ int main(void) { if (test_x509_crl_reason() != 1) goto err; if (test_x509_crl_entry_ext() != 1) goto err; if (test_x509_crl_entry_exts() != 1) goto err; if (test_x509_revoked_cert() != 1) goto err; if (test_vector_gen_uri_as_general_names() != 1) goto err; if (test_x509_crl_ext_id() != 1) goto err; if (test_x509_issuing_distribution_point() != 1) goto err; if (test_x509_issuing_distribution_point_from_der() != 1) goto err; if (test_x509_crl_exts() != 1) goto err; printf("%s all tests passed\n", __FILE__); return 0; err: error_print(); return 1; }