diff --git a/.gitignore b/.gitignore index 2619cec2..a7189d28 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,11 @@ /build* /demos/*.pem /demos/.private +/demos/scripts/*.pem +/demos/scripts/*.der +/demos/scripts/*.txt +/demos/scripts/*.bin +/demos/scripts/*.sig # Object files *.o diff --git a/demos/scripts/certverify.sh b/demos/scripts/certverify.sh new file mode 100755 index 00000000..56895c9b --- /dev/null +++ b/demos/scripts/certverify.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +signcert=ebssec.boc.cn-sign.pem +enccert=ebssec.boc.cn-enc.pem +crl=CFCA_SM2_OCA1.crl +cacert=CFCA_SM2_OCA1.pem +rootcacert=CFCA_CS_SM2_CA.pem + + +cat << EOF > $signcert +-----BEGIN CERTIFICATE----- +MIICzzCCAnKgAwIBAgIFEzY5M3AwDAYIKoEcz1UBg3UFADAlMQswCQYDVQQGEwJD +TjEWMBQGA1UECgwNQ0ZDQSBTTTIgT0NBMTAeFw0yMTA2MTEwOTA1MjBaFw0yNjA2 +MTkwODE2NTZaMIGRMQswCQYDVQQGEwJDTjEPMA0GA1UECAwG5YyX5LqsMQ8wDQYD +VQQHDAbljJfkuqwxJzAlBgNVBAoMHuS4reWbvemTtuihjOiCoeS7veaciemZkOWF +rOWPuDERMA8GA1UECwwITG9jYWwgUkExDDAKBgNVBAsMA1NTTDEWMBQGA1UEAwwN +ZWJzc2VjLmJvYy5jbjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABPsNUnoZQM9C +SnvC57TbvdfyOTCuPOSlZmPAyxBKFj+Y1QH/xlubHdVf5XqHrO1jCDRi7aN5IKGX +QF1492c803OjggEeMIIBGjAfBgNVHSMEGDAWgBRck1ggWiRzVhAbZFAQ7OmnygdB +ETAMBgNVHRMBAf8EAjAAMEgGA1UdIARBMD8wPQYIYIEchu8qAQEwMTAvBggrBgEF +BQcCARYjaHR0cDovL3d3dy5jZmNhLmNvbS5jbi91cy91cy0xNC5odG0wNwYDVR0f +BDAwLjAsoCqgKIYmaHR0cDovL2NybC5jZmNhLmNvbS5jbi9TTTIvY3JsNTYxOC5j +cmwwGAYDVR0RBBEwD4INZWJzc2VjLmJvYy5jbjAOBgNVHQ8BAf8EBAMCBsAwHQYD +VR0OBBYEFJ6oFo/OrKgDhHFORpaq04kX7T1KMB0GA1UdJQQWMBQGCCsGAQUFBwMC +BggrBgEFBQcDATAMBggqgRzPVQGDdQUAA0kAMEYCIQCvhSvbv5h6ERl1YcCLg+fz +9UleQbaPfBYwUjUD2dAHVQIhAMRC4k9S/mSC0UpUvCqh/DQC2Ui8Tccd5G2IgYSs +cnUN +-----END CERTIFICATE----- +EOF + +cat << EOF > $enccert +-----BEGIN CERTIFICATE----- +MIICzjCCAnKgAwIBAgIFEzY5M3EwDAYIKoEcz1UBg3UFADAlMQswCQYDVQQGEwJD +TjEWMBQGA1UECgwNQ0ZDQSBTTTIgT0NBMTAeFw0yMTA2MTEwOTA1MjBaFw0yNjA2 +MTkwODE2NTZaMIGRMQswCQYDVQQGEwJDTjEPMA0GA1UECAwG5YyX5LqsMQ8wDQYD +VQQHDAbljJfkuqwxJzAlBgNVBAoMHuS4reWbvemTtuihjOiCoeS7veaciemZkOWF +rOWPuDERMA8GA1UECwwITG9jYWwgUkExDDAKBgNVBAsMA1NTTDEWMBQGA1UEAwwN +ZWJzc2VjLmJvYy5jbjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABMn1q+hbV0i1 +qnKAy7QeZ3ZfAD+gqHX4F5MqIhsarODlWsavf/dcprC0F277zc44aYBB/3ucy4PF +qXaRHQp8PEyjggEeMIIBGjAfBgNVHSMEGDAWgBRck1ggWiRzVhAbZFAQ7OmnygdB +ETAMBgNVHRMBAf8EAjAAMEgGA1UdIARBMD8wPQYIYIEchu8qAQEwMTAvBggrBgEF +BQcCARYjaHR0cDovL3d3dy5jZmNhLmNvbS5jbi91cy91cy0xNC5odG0wNwYDVR0f +BDAwLjAsoCqgKIYmaHR0cDovL2NybC5jZmNhLmNvbS5jbi9TTTIvY3JsNTYxOC5j +cmwwGAYDVR0RBBEwD4INZWJzc2VjLmJvYy5jbjAOBgNVHQ8BAf8EBAMCAzgwHQYD +VR0OBBYEFF/a1JHvzLzbpFbBljX7hNxRpj/2MB0GA1UdJQQWMBQGCCsGAQUFBwMC +BggrBgEFBQcDATAMBggqgRzPVQGDdQUAA0gAMEUCIQDCOFi1eZcgiN6t+h6lxLwS +grAh3Jall+ZyA2ePw6xcjwIgNyDvo761dpwJhcyWfyVCAnaTf0Vf4DLWI1K+S7po +Ur8= +-----END CERTIFICATE----- +EOF + + +cat << EOF > $cacert +-----BEGIN CERTIFICATE----- +MIICNTCCAdmgAwIBAgIFEAAAAAgwDAYIKoEcz1UBg3UFADBYMQswCQYDVQQGEwJD +TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRcwFQYDVQQDDA5DRkNBIENTIFNNMiBDQTAeFw0xMzAxMjQwODQ2NDBaFw0z +MzAxMTkwODQ2NDBaMCUxCzAJBgNVBAYTAkNOMRYwFAYDVQQKDA1DRkNBIFNNMiBP +Q0ExMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEfJqQoo0+JoyCRy0msS2Ym076 +8nV1pSLuK9utS1ij38obWDymq0oMRRwUzDMEQI19Cajo3JUoGFxOvsA+YWu3XKOB +wDCBvTAfBgNVHSMEGDAWgBTkjt3Uo+e2D+4dJ5bNddwlJXJp3TAMBgNVHRMEBTAD +AQH/MGAGA1UdHwRZMFcwVaBToFGkTzBNMQswCQYDVQQGEwJDTjETMBEGA1UECgwK +Q0ZDQSBDUyBDQTEMMAoGA1UECwwDQ1JMMQwwCgYDVQQLDANTTTIxDTALBgNVBAMM +BGNybDEwCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBRck1ggWiRzVhAbZFAQ7OmnygdB +ETAMBggqgRzPVQGDdQUAA0gAMEUCIBVscoZJhUy4eToK4C//LjvhjKK2qpBFac/h +Pr6yYTLzAiEAiyqrqsGUU5vGkDo5bEpmF1EbnY8xovsM9vCx98yBrVM= +-----END CERTIFICATE----- +EOF + + +cat << EOF > $rootcacert +-----BEGIN CERTIFICATE----- +MIICAzCCAaegAwIBAgIEFy9CWTAMBggqgRzPVQGDdQUAMFgxCzAJBgNVBAYTAkNO +MTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkxFzAVBgNVBAMMDkNGQ0EgQ1MgU00yIENBMB4XDTEyMDgzMTAyMDY1OVoXDTQy +MDgyNDAyMDY1OVowWDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFu +Y2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEXMBUGA1UEAwwOQ0ZDQSBDUyBT +TTIgQ0EwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAATuRh26wmtyKNMz+Pmneo3a +Sme+BCjRon8SvAxZBgLSuIxNUewq4kNujeb1I4A0yg7xNcjuOgXglAoQv+Tc+P0V +o10wWzAfBgNVHSMEGDAWgBTkjt3Uo+e2D+4dJ5bNddwlJXJp3TAMBgNVHRMEBTAD +AQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU5I7d1KPntg/uHSeWzXXcJSVyad0w +DAYIKoEcz1UBg3UFAANIADBFAiBhP/rmIvles3RK1FfcmmEeS9RZdu+5lCzxF0nk +cof2QAIhAPVRpqOuceEQHsR77FBe/DgVPqF6lOyoZs0TzTDHrN8c +-----END CERTIFICATE----- +EOF + +gmssl certverify -in $signcert -cacert $cacert +gmssl certverify -in $enccert -cacert $cacert +gmssl certverify -in $cacert -cacert $rootcacert + +chain=chain.pem +cat $signcert > $chain +cat $cacert >> $chain +gmssl certverify -in $chain -cacert $rootcacert + +double_certs=double_certs.pem +cat $signcert > $double_certs +cat $enccert >> $double_certs +gmssl certverify -in $double_certs -cacert $cacert -double_certs + +double_chain=double_chain.pem +cat $double_certs > $double_chain +cat $cacert >> $double_chain +gmssl certverify -in $double_chain -cacert $rootcacert -double_certs + +gmssl certparse -in $double_chain +#gmssl certverify -in $double_chain -cacert $rootcacert -double_certs -check_crl +#gmssl crlget -cert $signcert -out $crl +#gmssl crlparse -in $crl + + +rm -fr $signcert +rm -fr $enccert +rm -fr $crl +rm -fr $cacert +rm -fr $rootcacert +rm -fr $chain +rm -fr $double_certs +rm -fr $double_chain + + diff --git a/tools/certverify.c b/tools/certverify.c index 742e387a..d184648a 100644 --- a/tools/certverify.c +++ b/tools/certverify.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ static const char *usage = " -in pem [-double_certs]" " [-check_crl]" " -cacert pem" + " [-sm2_id str | -sm2_id_hex hex]" "\n"; static const char *options = @@ -30,6 +32,12 @@ static const char *options = " -double_certs The first two certificates are SM2 signing and encryption entity certificate\n" " -check_crl If the entity certificate has CRLDistributionPoints extension, Download and check againt the CRL\n" " -cacert pem CA certificate\n" +" -sm2_id str Signer's ID in SM2 signature algorithm\n" +" -sm2_id_hex hex Signer's ID in hex format\n" +" When `-sm2_id` or `-sm2_id_hex` is specified,\n" +" must use the same ID in other commands explicitly.\n" +" If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n" +" the default string '1234567812345678' is used\n" "\n"; @@ -37,6 +45,8 @@ int certverify_main(int argc, char **argv) { int ret = 1; char *prog = argv[0]; + char *str; + char *infile = NULL; char *cacertfile = NULL; FILE *infp = stdin; @@ -45,10 +55,22 @@ int certverify_main(int argc, char **argv) size_t certlen; uint8_t cacert[1024]; size_t cacertlen; + char signer_id[SM2_MAX_ID_LENGTH + 1] = {0}; + size_t signer_id_len = 0; + + const uint8_t *serial; + size_t serial_len; + const uint8_t *issuer; + size_t issuer_len; const uint8_t *subject; size_t subject_len; - const uint8_t *subj; - size_t subj_len; + + const uint8_t *enc_serial; + size_t enc_serial_len; + const uint8_t *enc_issuer; + size_t enc_issuer_len; + const uint8_t *enc_subject; + size_t enc_subject_len; int double_certs = 0; uint8_t enc_cert[1024]; @@ -56,6 +78,7 @@ int certverify_main(int argc, char **argv) int rv; int check_crl = 0; + int crl_ret; argc--; argv++; @@ -89,6 +112,26 @@ int certverify_main(int argc, char **argv) fprintf(stderr, "%s: open '%s' failure : %s\n", prog, cacertfile, strerror(errno)); goto end; } + } else if (!strcmp(*argv, "-sm2_id")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > sizeof(signer_id) - 1) { + fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog); + goto end; + } + strncpy(signer_id, str, sizeof(signer_id)); + signer_id_len = strlen(str); + } else if (!strcmp(*argv, "-sm2_id_hex")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > (sizeof(signer_id) - 1) * 2) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog); + goto end; + } + if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog); + goto end; + } } else { fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); goto end; @@ -110,24 +153,34 @@ bad: fprintf(stderr, "%s: '-cacert' option required\n", prog); goto end; } + if (!signer_id_len) { + strcpy(signer_id, SM2_DEFAULT_ID); + signer_id_len = strlen(SM2_DEFAULT_ID); + } + // read first to be verified certificate if (x509_cert_from_pem(cert, &certlen, sizeof(cert), infp) != 1 + || x509_cert_get_issuer_and_serial_number(cert, certlen, + &issuer, &issuer_len, &serial, &serial_len) != 1 || x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1) { fprintf(stderr, "%s: read certificate failure\n", prog); goto end; } - x509_name_print(stdout, 0, 0, "Certificate", subject, subject_len); + format_print(stdout, 0, 0, "Certificate\n"); + format_bytes(stdout, 0, 4, "serialNumber", serial, serial_len); + x509_name_print(stdout, 0, 4, "subject", subject, subject_len); + // read encryption cert in double certs if (double_certs) { - if (x509_cert_from_pem(enc_cert, &enc_cert_len, sizeof(enc_cert), infp) != 1 - || x509_cert_get_subject(enc_cert, enc_cert_len, &subj, &subj_len) != 1) { + || x509_cert_get_issuer_and_serial_number(enc_cert, enc_cert_len, + &enc_issuer, &enc_issuer_len, &enc_serial, &enc_serial_len) != 1 + || x509_cert_get_subject(enc_cert, enc_cert_len, &enc_subject, &enc_subject_len) != 1) { fprintf(stderr, "%s: read encryption certficate failure\n", prog); goto end; } - - if (subj_len != subject_len - || memcmp(subject, subj, subj_len) != 0) { + if (x509_name_equ(enc_subject, enc_subject_len, subject, subject_len) != 1 + || x509_name_equ(enc_issuer, enc_issuer_len, issuer, issuer_len) != 1) { fprintf(stderr, "%s: double certificates not compatible\n", prog); goto end; } @@ -138,73 +191,117 @@ bad: if (rv < 0) goto end; goto final; } - if (x509_cert_get_subject(cacert, cacertlen, &subject, &subject_len) != 1) { - goto end; - } - if ((rv = x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) { - fprintf(stderr, "%s: inner error\n", prog); + if ((rv = x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + signer_id, signer_id_len)) != 1) { + fprintf(stderr, "%s: Verification failure\n", prog); goto end; } - printf("Verification %s\n", rv ? "success" : "failure"); + format_print(stdout, 0, 4, "Verification success\n"); if (check_crl) { - if (x509_cert_check_crl(cert, certlen, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) < 0) { - fprintf(stderr, "%s: certificate has been revoked\n", prog); + if ((crl_ret = x509_cert_check_crl(cert, certlen, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: Certificate has been revoked\n", prog); goto end; } + format_print(stdout, 0, 4, "Revocation status: %s\n", + crl_ret ? "Not revoked by CRL" : "No CRL URI found in certificate"); } - if (double_certs) { - x509_name_print(stdout, 0, 0, "Certificate", subj, subj_len); - if ((rv = x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) { - fprintf(stderr, "%s: inner error\n", prog); + if (double_certs) { + if ((rv = x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: Verification failure\n", prog); goto end; } - printf("Verification %s\n", rv ? "success" : "failure"); - double_certs = 0; - + format_print(stdout, 0, 0, "Certificate\n"); + format_bytes(stdout, 0, 4, "serialNumber", enc_serial, enc_serial_len); + x509_name_print(stdout, 0, 4, "subject", enc_subject, enc_subject_len); + format_print(stdout, 0, 4, "Verification success\n"); if (check_crl) { - if (x509_cert_check_crl(enc_cert, enc_cert_len, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) < 0) { - fprintf(stderr, "%s: certificate has been revoked\n", prog); + if ((crl_ret = x509_cert_check_crl(enc_cert, enc_cert_len, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: Certificate has been revoked\n", prog); goto end; } + format_print(stdout, 0, 4, "Revocation status: %s\n", + crl_ret ? "Not revoked by CRL" : "No CRL URI found in certificate"); } + double_certs = 0; } - format_print(stdout, 0, 0, "Signed by\n"); - x509_name_print(stdout, 0, 0, "Certificate", subject, subject_len); + + // NOTE: make sure the buffer (issuer, issuer_len) not crashed + memcpy(cert, cacert, cacertlen); + certlen = cacertlen; + if (x509_cert_get_issuer_and_serial_number(cert, certlen, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1) { + error_print(); + goto end; + } + format_print(stdout, 0, 0, "Signed by Certificate\n"); + format_bytes(stdout, 0, 4, "serialNumber", serial, serial_len); + x509_name_print(stdout, 0, 4, "Certificate", subject, subject_len); check_crl = 0; // only check the entity CRL - memcpy(cert, cacert, cacertlen); - certlen = cacertlen; } final: - if (x509_cert_get_issuer(cert, certlen, &subject, &subject_len) != 1) { - fprintf(stderr, "%s: parse certificate error\n", prog); - goto end; - } - if (x509_cert_from_pem_by_subject(cacert, &cacertlen, sizeof(cacert), subject, subject_len, cacertfp) != 1) { + if (x509_cert_from_pem_by_subject(cacert, &cacertlen, sizeof(cacert), issuer, issuer_len, cacertfp) != 1) { fprintf(stderr, "%s: load CA certificate failure\n", prog); goto end; } - if ((rv = x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) { + if ((rv = x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { fprintf(stderr, "%s: inner error\n", prog); goto end; } - printf("Verification %s\n", rv ? "success" : "failure"); - format_print(stdout, 0, 0, "Signed by\n"); - x509_name_print(stdout, 0, 0, "Certificate", subject, subject_len); + format_print(stdout, 0, 4, "Verification success\n"); + + if (check_crl) { + if ((crl_ret = x509_cert_check_crl(cert, certlen, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: certificate has been revoked\n", prog); + goto end; + } + format_print(stdout, 0, 4, "Revocation status: %s\n", + crl_ret ? "Not revoked by CRL" : "No CRL URI found in certificate"); + } if (double_certs) { - if ((rv = x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) { + if ((rv = x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { fprintf(stderr, "%s: inner error\n", prog); goto end; } - printf("Verification %s\n", rv ? "success" : "failure"); + format_print(stdout, 0, 0, "Certificate\n"); + format_bytes(stdout, 0, 4, "serialNumber", enc_serial, enc_serial_len); + x509_name_print(stdout, 0, 4, "subject", enc_subject, enc_subject_len); + format_print(stdout, 0, 4, "Verification success\n"); + + if (check_crl) { + if ((crl_ret = x509_cert_check_crl(enc_cert, enc_cert_len, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: certificate has been revoked\n", prog); + goto end; + } + format_print(stdout, 0, 4, "Revocation status: %s\n", + crl_ret ? "Not revoked by CRL" : "No CRL URI found in certificate"); + } } + + if (x509_cert_get_issuer_and_serial_number(cacert, cacertlen, NULL, NULL, &serial, &serial_len) != 1 + || x509_cert_get_subject(cacert, cacertlen, &subject, &subject_len) != 1) { + fprintf(stderr, "%s: parse certificate error\n", prog); + goto end; + } + format_print(stdout, 0, 0, "Signed by Certificate\n"); + format_bytes(stdout, 0, 4, "serialNumber", serial, serial_len); + x509_name_print(stdout, 0, 4, "subject", subject, subject_len); + printf("\n"); ret = 0;