int main(int argc, char *argv[]) { int ret = 1; int i; gnutls_pubkey_t pubkey = NULL; gnutls_x509_privkey_t sigkey = NULL; gnutls_x509_crt_t sigcert = NULL; gnutls_x509_crt_t crt = NULL; const char *pubkey_filename = NULL; const char *sigkey_filename = NULL; const char *cert_filename = NULL; const char *modulus_str = NULL; const char *issuercert_filename = NULL; unsigned char *modulus_bin = NULL; int modulus_len = 0; gnutls_datum_t datum = { NULL, 0}, out = { NULL, 0}; int serial = 1; time_t now; int err; FILE *cert_file; char *subject = NULL; const char *error = NULL; int days = 365; char *sigkeypass = NULL; uint32_t ser_number; long int exponent = 0x10001; bool write_pem = false; uint8_t id[512]; size_t id_size = sizeof(id); enum cert_type_t certtype = CERT_TYPE_EK; const char *oid; unsigned int key_usage; char *tpm_manufacturer = NULL; char *tpm_version = NULL; char *tpm_model = NULL; char *platf_manufacturer = NULL; char *platf_version = NULL; char *platf_model = NULL; i = 1; while (i < argc) { if (!strcmp(argv[i], "--pubkey")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --pubkey.\n"); goto cleanup; } pubkey_filename = argv[i]; } else if (!strcmp(argv[i], "--modulus")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --modulus.\n"); goto cleanup; } modulus_str = argv[i]; if (!(modulus_bin = hex_str_to_bin(modulus_str, &modulus_len))) { goto cleanup; } } else if (!strcmp(argv[i], "--exponent")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --exponent.\n"); goto cleanup; } exponent = strtol(argv[i], NULL, 0); if (exponent == 0) { fprintf(stderr, "Exponent is wrong and cannot be 0.\n"); goto cleanup; } if (exponent > UINT_MAX) { fprintf(stderr, "Exponent must fit into 32bits.\n"); goto cleanup; } } else if (!strcmp(argv[i], "--signkey")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --signkey.\n"); goto cleanup; } sigkey_filename = argv[i]; } else if (!strcmp(argv[i], "--signkey-password")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --signkey-password.\n"); goto cleanup; } sigkeypass = argv[i]; } else if (!strcmp(argv[i], "--issuercert")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --issuercert.\n"); goto cleanup; } issuercert_filename = argv[i]; } else if (!strcmp(argv[i], "--out-cert")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --out-cert.\n"); goto cleanup; } cert_filename = argv[i]; } else if (!strcmp(argv[i], "--subject")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --subject.\n"); goto cleanup; } subject = argv[i]; } else if (!strcmp(argv[i], "--days")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --days.\n"); goto cleanup; } days = atoi(argv[i]); } else if (!strcmp(argv[i], "--serial")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --serial.\n"); goto cleanup; } serial = atoi(argv[i]); } else if (!strcmp(argv[i], "--type")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --type.\n"); goto cleanup; } if (!strcasecmp(argv[i], "ek")) { certtype = CERT_TYPE_EK; } else if (!strcasecmp(argv[i], "platform")) { certtype = CERT_TYPE_PLATFORM; // } else if (!strcasecmp(argv[i], "aik")) { // /* AIK cert needs EK cert as input */ // certtype = CERT_TYPE_AIK; } else { fprintf(stderr, "Unknown certificate type '%s'.\n", argv[i]); goto cleanup; } } else if (!strcmp(argv[i], "--tpm-manufacturer")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --tpm-manufacturer.\n"); goto cleanup; } tpm_manufacturer = argv[i]; } else if (!strcmp(argv[i], "--tpm-model")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --tpm-model.\n"); goto cleanup; } tpm_model = argv[i]; } else if (!strcmp(argv[i], "--tpm-version")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --tpm-version.\n"); goto cleanup; } tpm_version = argv[i]; } else if (!strcmp(argv[i], "--platform-manufacturer")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --platform-manufacturer.\n"); goto cleanup; } platf_manufacturer = argv[i]; } else if (!strcmp(argv[i], "--platform-model")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --platform-model.\n"); goto cleanup; } platf_model = argv[i]; } else if (!strcmp(argv[i], "--platform-version")) { i++; if (i == argc) { fprintf(stderr, "Missing argument for --platform-version.\n"); goto cleanup; } platf_version = argv[i]; } else if (!strcmp(argv[i], "--pem")) { write_pem = true; } else if (!strcmp(argv[i], "--help")) { usage(argv[0]); exit(0); } else { fprintf(stderr, "Unknown command line parameter '%s'.\n", argv[i]); usage(argv[0]); exit(1); } i++; } ser_number = htonl(serial); if (pubkey_filename == NULL && modulus_bin == NULL) { fprintf(stderr, "Missing public EK file and modulus.\n"); usage(argv[0]); goto cleanup; } if (issuercert_filename == NULL) { fprintf(stderr, "The issuer certificate name is required.\n"); goto cleanup; } switch (certtype) { case CERT_TYPE_EK: case CERT_TYPE_PLATFORM: if (tpm_manufacturer == NULL || tpm_model == NULL || tpm_version == NULL) { fprintf(stderr, "--tpm-manufacturer and --tpm-model and " "--tpm version " "must all be provided\n"); goto cleanup; } break; case CERT_TYPE_AIK: break; } switch (certtype) { case CERT_TYPE_PLATFORM: if (platf_manufacturer == NULL || platf_model == NULL || platf_version == NULL) { fprintf(stderr, "--platform-manufacturer and --platform-model and " "--platform version " "must all be provided\n"); goto cleanup; } break; case CERT_TYPE_EK: case CERT_TYPE_AIK: break; } err = gnutls_global_init(); if (err < 0) { fprintf(stderr, "gnutls_global_init failed.\n"); goto cleanup; } gnutls_x509_privkey_init(&sigkey); if (pubkey_filename) { gnutls_pubkey_init(&pubkey); err = gnutls_load_file(pubkey_filename, &datum); if (err != GNUTLS_E_SUCCESS) { fprintf(stderr, "Could not open file for EK public key: %s\n", strerror(errno)); goto cleanup; } err = gnutls_pubkey_import(pubkey, &datum, GNUTLS_X509_FMT_PEM); gnutls_free(datum.data); datum.data = NULL; if (err != GNUTLS_E_SUCCESS) { fprintf(stderr, "Could not import EK.\n"); goto cleanup; } } else { pubkey = create_rsa_from_modulus(modulus_bin, modulus_len, exponent); free(modulus_bin); modulus_bin = NULL; if (pubkey == NULL) goto cleanup; } /* all types of keys must have pubkey set now otherwise the signing will not work */ if (sigkey_filename == NULL) { fprintf(stderr, "Missing signature key.\n"); usage(argv[0]); exit(1); } #define CHECK_GNUTLS_ERROR(_err, _msg, ...) \ if (_err != GNUTLS_E_SUCCESS) { \ fprintf(stderr, _msg, __VA_ARGS__); \ goto cleanup; \ } err = gnutls_load_file(sigkey_filename, &datum); CHECK_GNUTLS_ERROR(err, "Could not read signing key from file %s: %s\n", sigkey_filename, gnutls_strerror(err)); if (sigkeypass) { err = gnutls_x509_privkey_import2(sigkey, &datum, GNUTLS_X509_FMT_PEM, sigkeypass, 0); } else { err = gnutls_x509_privkey_import(sigkey, &datum, GNUTLS_X509_FMT_PEM); } gnutls_free(datum.data); datum.data = NULL; CHECK_GNUTLS_ERROR(err, "Could not import signing key : %s\n", gnutls_strerror(err)); err = gnutls_load_file(issuercert_filename, &datum); CHECK_GNUTLS_ERROR(err, "Could not read certificate from file %s : %s\n", issuercert_filename, gnutls_strerror(err)); gnutls_x509_crt_init(&sigcert); err = gnutls_x509_crt_import(sigcert, &datum, GNUTLS_X509_FMT_PEM); gnutls_free(datum.data); datum.data = NULL; CHECK_GNUTLS_ERROR(err, "Could not import issuer certificate: %s\n", gnutls_strerror(err)); err = gnutls_x509_crt_init(&crt); CHECK_GNUTLS_ERROR(err, "CRT init failed: %s\n", gnutls_strerror(err)) /* 3.5.1 Version */ err = gnutls_x509_crt_set_version(crt, 3); CHECK_GNUTLS_ERROR(err, "Could not set version on CRT: %s\n", gnutls_strerror(err)) /* 3.5.2 Serial Number */ err = gnutls_x509_crt_set_serial(crt, &ser_number, sizeof(ser_number)); CHECK_GNUTLS_ERROR(err, "Could not set serial on CRT: %s\n", gnutls_strerror(err)) /* 3.5.5 Validity */ now = time(NULL); err = gnutls_x509_crt_set_activation_time(crt, now); CHECK_GNUTLS_ERROR(err, "Could not set activation time on CRT: %s\n", gnutls_strerror(err)) err = gnutls_x509_crt_set_expiration_time(crt, now + (time_t)days * 24 * 60 * 60); CHECK_GNUTLS_ERROR(err, "Could not set expiration time on CRT: %s\n", gnutls_strerror(err)) /* 3.5.6 Subject -- should be empty, but we allow it anyway */ if (subject) { err = gnutls_x509_crt_set_dn(crt, subject, &error); CHECK_GNUTLS_ERROR(err, "Could not set DN on CRT: %s\n" "DN '%s must be fault after %s\n.'", gnutls_strerror(err), subject, error) } /* 3.5.7 Public Key Info */ switch (certtype) { case CERT_TYPE_EK: oid = "1.2.840.113549.1.1.7"; break; case CERT_TYPE_PLATFORM: oid = NULL; break; case CERT_TYPE_AIK: oid = "1.2.840.113549.1.1.1"; break; default: fprintf(stderr, "Internal error: unhandle case in line %d\n", __LINE__); goto cleanup; } if (oid) { err = gnutls_x509_crt_set_key_purpose_oid(crt, oid, 0); CHECK_GNUTLS_ERROR(err, "Could not set key purpose on CRT: %s\n", gnutls_strerror(err)) } /* 3.5.8 Certificate Policies -- skip since not mandated */ /* 3.5.9 Subject Alternative Names -- missing code */ err = create_tpm_manufacturer_info(tpm_manufacturer, tpm_model, tpm_version, &datum); if (!err && datum.size > 0) { /* * GNUTLS's write_new_general_name can only handle a few GNUTLS_SAN_* * -> we have to use GNUTLS_SAN_URI */ err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_URI, datum.data, datum.size, GNUTLS_FSAN_SET); CHECK_GNUTLS_ERROR(err, "Could not set subject alt name: %s\n", gnutls_strerror(err)) }
void doit(void) { gnutls_x509_privkey_t pkey; gnutls_x509_crt_t crt; gnutls_x509_crt_t crt2; const char *err = NULL; gnutls_datum_t out; size_t s = 0; int ret; ret = global_init(); if (ret < 0) fail("global_init\n"); gnutls_global_set_time_function(mytime); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(4711); ret = gnutls_x509_crt_init(&crt); if (ret != 0) fail("gnutls_x509_crt_init\n"); ret = gnutls_x509_crt_init(&crt2); if (ret != 0) fail("gnutls_x509_crt_init\n"); ret = gnutls_x509_crt_import(crt2, &server_ecc_cert, GNUTLS_X509_FMT_PEM); if (ret != 0) fail("gnutls_x509_crt_import\n"); ret = gnutls_x509_privkey_init(&pkey); if (ret != 0) fail("gnutls_x509_privkey_init\n"); ret = gnutls_x509_privkey_import(pkey, &key_dat, GNUTLS_X509_FMT_PEM); if (ret != 0) fail("gnutls_x509_privkey_import\n"); /* Setup CRT */ ret = gnutls_x509_crt_set_version(crt, 3); if (ret != 0) fail("gnutls_x509_crt_set_version\n"); ret = gnutls_x509_crt_set_serial(crt, "\x0a\x11\x00", 3); if (ret != 0) fail("gnutls_x509_crt_set_serial\n"); ret = gnutls_x509_crt_set_expiration_time(crt, -1); if (ret != 0) fail("error\n"); ret = gnutls_x509_crt_set_activation_time(crt, mytime(0)); if (ret != 0) fail("error\n"); ret = gnutls_x509_crt_set_key(crt, pkey); if (ret != 0) fail("gnutls_x509_crt_set_key\n"); ret = gnutls_x509_crt_set_basic_constraints(crt, 0, -1); if (ret < 0) { fail("error\n"); } ret = gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_DIGITAL_SIGNATURE); if (ret != 0) fail("gnutls_x509_crt_set_key_usage %d\n", ret); ret = gnutls_x509_crt_set_dn(crt, "o = none to\\, mention,cn = nikos", &err); if (ret < 0) { fail("gnutls_x509_crt_set_dn: %s, %s\n", gnutls_strerror(ret), err); } ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME, "foo", 3, 1); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME, "*****@*****.**", strlen("*****@*****.**"), 1); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME, "ινβάλιντ@bar.org", strlen("ινβάλιντ@bar.org"), 1); if (ret != GNUTLS_E_INVALID_UTF8_EMAIL) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS, "\xc1\x5c\x96\x3", 4, 1); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 16, 1); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME, "apa", 3, 0); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME, "απαλό.com", strlen("απαλό.com"), 1); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); #ifdef HAVE_LIBIDN ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME, "test@νίκο.org", strlen("test@νίκο.org"), 1); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); #endif s = 0; ret = gnutls_x509_crt_get_key_purpose_oid(crt, 0, NULL, &s, NULL); if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) fail("gnutls_x509_crt_get_key_purpose_oid %d\n", ret); s = 0; ret = gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0); if (ret != 0) fail("gnutls_x509_crt_set_key_purpose_oid %d\n", ret); s = 0; ret = gnutls_x509_crt_get_key_purpose_oid(crt, 0, NULL, &s, NULL); if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) fail("gnutls_x509_crt_get_key_purpose_oid %d\n", ret); s = 0; ret = gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_CLIENT, 1); if (ret != 0) fail("gnutls_x509_crt_set_key_purpose_oid2 %d\n", ret); ret = gnutls_x509_crt_set_issuer_dn(crt, "cn = my CA, o = big\\, and one", &err); if (ret < 0) { fail("gnutls_x509_crt_set_issuer_dn: %s, %s\n", gnutls_strerror(ret), err); } ret = gnutls_x509_crt_sign2(crt, crt, pkey, GNUTLS_DIG_SHA256, 0); if (ret < 0) fail("gnutls_x509_crt_sign2: %s\n", gnutls_strerror(ret)); ret = gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_FULL, &out); if (ret != 0) fail("gnutls_x509_crt_print\n"); if (debug) printf("crt: %.*s\n", out.size, out.data); gnutls_free(out.data); s = 0; ret = gnutls_x509_crt_get_extension_info(crt, 0, NULL, &s, NULL); if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) fail("gnutls_x509_crt_get_extension_info2: %s\n", strerror(ret)); s = 0; ret = gnutls_x509_crt_get_extension_data(crt, 0, NULL, &s); if (ret != 0) fail("gnutls_x509_crt_get_extension_data: %s\n", strerror(ret)); ret = gnutls_x509_crt_get_raw_issuer_dn(crt, &out); if (ret < 0 || out.size == 0) fail("gnutls_x509_crt_get_raw_issuer_dn: %s\n", gnutls_strerror(ret)); if (out.size != 45 || memcmp(out.data, "\x30\x2b\x31\x0e\x30\x0c\x06\x03\x55\x04\x03\x13\x05\x6e\x69\x6b\x6f\x73\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x6e\x6f\x6e\x65\x20\x74\x6f\x2c\x20\x6d\x65\x6e\x74\x69\x6f\x6e", 45) != 0) { hexprint(out.data, out.size); fail("issuer DN comparison failed\n"); } gnutls_free(out.data); ret = gnutls_x509_crt_get_raw_dn(crt, &out); if (ret < 0 || out.size == 0) fail("gnutls_x509_crt_get_raw_dn: %s\n", gnutls_strerror(ret)); if (out.size != 45 || memcmp(out.data, "\x30\x2b\x31\x0e\x30\x0c\x06\x03\x55\x04\x03\x13\x05\x6e\x69\x6b\x6f\x73\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x6e\x6f\x6e\x65\x20\x74\x6f\x2c\x20\x6d\x65\x6e\x74\x69\x6f\x6e", 45) != 0) { fail("DN comparison failed\n"); } gnutls_free(out.data); ret = gnutls_x509_crt_equals(crt, crt); if (ret == 0) { fail("equality test failed\n"); } ret = gnutls_x509_crt_equals(crt, crt2); if (ret != 0) { fail("equality test failed\n"); } assert(gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_PEM, &out) >= 0); #ifdef HAVE_LIBIDN assert(out.size == saved_crt.size); assert(memcmp(out.data, saved_crt.data, out.size)==0); #endif gnutls_free(out.data); gnutls_x509_crt_deinit(crt); gnutls_x509_crt_deinit(crt2); gnutls_x509_privkey_deinit(pkey); gnutls_global_deinit(); }
void doit(void) { gnutls_x509_privkey_t pkey; gnutls_x509_crt_t crt; gnutls_x509_crt_t crt2; const char *err = NULL; unsigned char buf[64]; gnutls_datum_t out; size_t s = 0; int ret; ret = global_init(); if (ret < 0) fail("global_init\n"); gnutls_global_set_time_function(mytime); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(4711); ret = gnutls_x509_crt_init(&crt); if (ret != 0) fail("gnutls_x509_crt_init\n"); ret = gnutls_x509_crt_init(&crt2); if (ret != 0) fail("gnutls_x509_crt_init\n"); ret = gnutls_x509_crt_import(crt2, &server_ecc_cert, GNUTLS_X509_FMT_PEM); if (ret != 0) fail("gnutls_x509_crt_import\n"); ret = gnutls_x509_privkey_init(&pkey); if (ret != 0) fail("gnutls_x509_privkey_init\n"); ret = gnutls_x509_privkey_import(pkey, &key_dat, GNUTLS_X509_FMT_PEM); if (ret != 0) fail("gnutls_x509_privkey_import\n"); /* Setup CRT */ ret = gnutls_x509_crt_set_version(crt, 3); if (ret != 0) fail("gnutls_x509_crt_set_version\n"); ret = gnutls_x509_crt_set_serial(crt, "\x0a\x11\x00", 3); if (ret != 0) fail("gnutls_x509_crt_set_serial\n"); ret = gnutls_x509_crt_set_expiration_time(crt, -1); if (ret != 0) fail("error\n"); ret = gnutls_x509_crt_set_activation_time(crt, mytime(0)); if (ret != 0) fail("error\n"); ret = gnutls_x509_crt_set_key(crt, pkey); if (ret != 0) fail("gnutls_x509_crt_set_key\n"); ret = gnutls_x509_crt_set_basic_constraints(crt, 0, -1); if (ret < 0) { fail("error\n"); } ret = gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_DIGITAL_SIGNATURE); if (ret != 0) fail("gnutls_x509_crt_set_key_usage %d\n", ret); ret = gnutls_x509_crt_set_dn(crt, "o = none to\\, mention,cn = nikos", &err); if (ret < 0) { fail("gnutls_x509_crt_set_dn: %s, %s\n", gnutls_strerror(ret), err); } ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME, "foo", 3, 1); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME, "*****@*****.**", strlen("*****@*****.**"), 1); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME, "ινβάλιντ@bar.org", strlen("ινβάλιντ@bar.org"), 1); if (ret != GNUTLS_E_INVALID_UTF8_EMAIL) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS, "\xc1\x5c\x96\x3", 4, 1); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 16, 1); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME, "apa", 3, 0); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME, "απαλό.com", strlen("απαλό.com"), 1); #if defined(HAVE_LIBIDN2) || defined(HAVE_LIBIDN) if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name: %s\n", gnutls_strerror(ret)); ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME, "test@νίκο.org", strlen("test@νίκο.org"), 1); if (ret != 0) fail("gnutls_x509_crt_set_subject_alt_name\n"); #else if (ret != GNUTLS_E_UNIMPLEMENTED_FEATURE) fail("gnutls_x509_crt_set_subject_alt_name: %s\n", gnutls_strerror(ret)); #endif s = 0; ret = gnutls_x509_crt_get_key_purpose_oid(crt, 0, NULL, &s, NULL); if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) fail("gnutls_x509_crt_get_key_purpose_oid %d\n", ret); s = 0; ret = gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0); if (ret != 0) fail("gnutls_x509_crt_set_key_purpose_oid %d\n", ret); s = 0; ret = gnutls_x509_crt_get_key_purpose_oid(crt, 0, NULL, &s, NULL); if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) fail("gnutls_x509_crt_get_key_purpose_oid %d\n", ret); s = 0; ret = gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_CLIENT, 1); if (ret != 0) fail("gnutls_x509_crt_set_key_purpose_oid2 %d\n", ret); /* in the end this will be ignored as the issuer will be set * by gnutls_x509_crt_sign2() */ ret = gnutls_x509_crt_set_issuer_dn(crt, "cn = my CA, o = big\\, and one", &err); if (ret < 0) { fail("gnutls_x509_crt_set_issuer_dn: %s, %s\n", gnutls_strerror(ret), err); } #define ISSUER_UNIQUE_ID "\x00\x01\x02\x03" #define SUBJECT_UNIQUE_ID "\x04\x03\x02\x01" ret = gnutls_x509_crt_set_issuer_unique_id(crt, ISSUER_UNIQUE_ID, sizeof(ISSUER_UNIQUE_ID)-1); if (ret < 0) fail("error: %s\n", gnutls_strerror(ret)); ret = gnutls_x509_crt_set_subject_unique_id(crt, SUBJECT_UNIQUE_ID, sizeof(SUBJECT_UNIQUE_ID)-1); if (ret < 0) fail("error: %s\n", gnutls_strerror(ret)); /* Sign and finalize the certificate */ ret = gnutls_x509_crt_sign2(crt, crt, pkey, GNUTLS_DIG_SHA256, 0); if (ret < 0) fail("gnutls_x509_crt_sign2: %s\n", gnutls_strerror(ret)); ret = gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_FULL, &out); if (ret != 0) fail("gnutls_x509_crt_print\n"); if (debug) printf("crt: %.*s\n", out.size, out.data); gnutls_free(out.data); /* Verify whether selected input is present */ s = 0; ret = gnutls_x509_crt_get_extension_info(crt, 0, NULL, &s, NULL); if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) fail("gnutls_x509_crt_get_extension_info2: %s\n", strerror(ret)); s = 0; ret = gnutls_x509_crt_get_extension_data(crt, 0, NULL, &s); if (ret != 0) fail("gnutls_x509_crt_get_extension_data: %s\n", strerror(ret)); ret = gnutls_x509_crt_get_raw_issuer_dn(crt, &out); if (ret < 0 || out.size == 0) fail("gnutls_x509_crt_get_raw_issuer_dn: %s\n", gnutls_strerror(ret)); if (out.size != 45 || memcmp(out.data, "\x30\x2b\x31\x0e\x30\x0c\x06\x03\x55\x04\x03\x13\x05\x6e\x69\x6b\x6f\x73\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x6e\x6f\x6e\x65\x20\x74\x6f\x2c\x20\x6d\x65\x6e\x74\x69\x6f\x6e", 45) != 0) { hexprint(out.data, out.size); fail("issuer DN comparison failed\n"); } gnutls_free(out.data); s = sizeof(buf); ret = gnutls_x509_crt_get_issuer_unique_id(crt, (void*)buf, &s); if (ret < 0) fail("error: %s\n", gnutls_strerror(ret)); if (s != sizeof(ISSUER_UNIQUE_ID)-1 || memcmp(buf, ISSUER_UNIQUE_ID, s) != 0) { fail("issuer unique id comparison failed\n"); } s = sizeof(buf); ret = gnutls_x509_crt_get_subject_unique_id(crt, (void*)buf, &s); if (ret < 0) fail("error: %s\n", gnutls_strerror(ret)); if (s != sizeof(SUBJECT_UNIQUE_ID)-1 || memcmp(buf, SUBJECT_UNIQUE_ID, s) != 0) { fail("subject unique id comparison failed\n"); } ret = gnutls_x509_crt_get_raw_dn(crt, &out); if (ret < 0 || out.size == 0) fail("gnutls_x509_crt_get_raw_dn: %s\n", gnutls_strerror(ret)); if (out.size != 45 || memcmp(out.data, "\x30\x2b\x31\x0e\x30\x0c\x06\x03\x55\x04\x03\x13\x05\x6e\x69\x6b\x6f\x73\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x6e\x6f\x6e\x65\x20\x74\x6f\x2c\x20\x6d\x65\x6e\x74\x69\x6f\x6e", 45) != 0) { fail("DN comparison failed\n"); } gnutls_free(out.data); ret = gnutls_x509_crt_equals(crt, crt); if (ret == 0) { fail("equality test failed\n"); } ret = gnutls_x509_crt_equals(crt, crt2); if (ret != 0) { fail("equality test failed\n"); } assert(gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_PEM, &out) >= 0); if (debug) fprintf(stderr, "%s\n", out.data); #if defined(HAVE_LIBIDN2) assert(out.size == saved_crt.size); assert(memcmp(out.data, saved_crt.data, out.size)==0); #endif gnutls_free(out.data); gnutls_x509_crt_deinit(crt); gnutls_x509_crt_deinit(crt2); gnutls_x509_privkey_deinit(pkey); gnutls_global_deinit(); }