static void privkey_info_int(FILE *outfile, common_info_st * cinfo, gnutls_x509_privkey_t key) { int ret, key_type; unsigned int bits = 0; size_t size; const char *cprint; /* Public key algorithm */ fprintf(outfile, "Public Key Info:\n"); ret = gnutls_x509_privkey_get_pk_algorithm2(key, &bits); fprintf(outfile, "\tPublic Key Algorithm: "); key_type = ret; cprint = gnutls_pk_algorithm_get_name(key_type); fprintf(outfile, "%s\n", cprint ? cprint : "Unknown"); fprintf(outfile, "\tKey Security Level: %s (%u bits)\n\n", gnutls_sec_param_get_name(gnutls_x509_privkey_sec_param (key)), bits); /* Print the raw public and private keys */ if (key_type == GNUTLS_PK_RSA) { gnutls_datum_t m, e, d, p, q, u, exp1, exp2; ret = gnutls_x509_privkey_export_rsa_raw2(key, &m, &e, &d, &p, &q, &u, &exp1, &exp2); if (ret < 0) fprintf(stderr, "Error in key RSA data export: %s\n", gnutls_strerror(ret)); else { print_rsa_pkey(outfile, &m, &e, &d, &p, &q, &u, &exp1, &exp2, cinfo->cprint); gnutls_free(m.data); gnutls_free(e.data); gnutls_free(d.data); gnutls_free(p.data); gnutls_free(q.data); gnutls_free(u.data); gnutls_free(exp1.data); gnutls_free(exp2.data); } } else if (key_type == GNUTLS_PK_DSA) { gnutls_datum_t p, q, g, y, x; ret = gnutls_x509_privkey_export_dsa_raw(key, &p, &q, &g, &y, &x); if (ret < 0) fprintf(stderr, "Error in key DSA data export: %s\n", gnutls_strerror(ret)); else { print_dsa_pkey(outfile, &x, &y, &p, &q, &g, cinfo->cprint); gnutls_free(x.data); gnutls_free(y.data); gnutls_free(p.data); gnutls_free(q.data); gnutls_free(g.data); } } else if (key_type == GNUTLS_PK_EC) { gnutls_datum_t y, x, k; gnutls_ecc_curve_t curve; ret = gnutls_x509_privkey_export_ecc_raw(key, &curve, &x, &y, &k); if (ret < 0) fprintf(stderr, "Error in key ECC data export: %s\n", gnutls_strerror(ret)); else { cprint = gnutls_ecc_curve_get_name(curve); bits = 0; print_ecc_pkey(outfile, curve, &k, &x, &y, cinfo->cprint); gnutls_free(x.data); gnutls_free(y.data); gnutls_free(k.data); } } fprintf(outfile, "\n"); size = lbuffer_size; ret = gnutls_x509_privkey_get_seed(key, NULL, lbuffer, &size); if (ret >= 0) { fprintf(outfile, "Seed: %s\n", raw_to_string(lbuffer, size)); } size = lbuffer_size; ret = gnutls_x509_privkey_get_key_id(key, GNUTLS_KEYID_USE_SHA256, lbuffer, &size); if (ret < 0) { fprintf(stderr, "Error in key id calculation: %s\n", gnutls_strerror(ret)); } else { gnutls_datum_t art; fprintf(outfile, "Public Key ID:\n\tsha256:%s\n", raw_to_string(lbuffer, size)); size = lbuffer_size; ret = gnutls_x509_privkey_get_key_id(key, GNUTLS_KEYID_USE_SHA1, lbuffer, &size); if (ret >= 0) { fprintf(outfile, "\tsha1:%s\n", raw_to_string(lbuffer, size)); } ret = gnutls_random_art(GNUTLS_RANDOM_ART_OPENSSH, cprint, bits, lbuffer, size, &art); if (ret >= 0) { fprintf(outfile, "Public key's random art:\n%s\n", art.data); gnutls_free(art.data); } } fprintf(outfile, "\n"); }
char * irc_sasl_mechanism_ecdsa_nist256p_challenge (struct t_irc_server *server, const char *data_base64, const char *sasl_username, const char *sasl_key) { #if defined(HAVE_GNUTLS) && (LIBGNUTLS_VERSION_NUMBER >= 0x030015) /* 3.0.21 */ char *data, *string, *answer_base64; int length_data, length_username, length, ret; char *str_privkey; gnutls_x509_privkey_t x509_privkey; gnutls_privkey_t privkey; gnutls_datum_t filedatum, decoded_data, signature; #if LIBGNUTLS_VERSION_NUMBER >= 0x030300 /* 3.3.0 */ gnutls_ecc_curve_t curve; gnutls_datum_t x, y, k; char *pubkey, *pubkey_base64; #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x030300 */ answer_base64 = NULL; string = NULL; length = 0; if (strcmp (data_base64, "+") == 0) { /* send "username" + '\0' + "username" */ answer_base64 = NULL; length_username = strlen (sasl_username); length = length_username + 1 + length_username; string = malloc (length + 1); if (string) { snprintf (string, length + 1, "%s|%s", sasl_username, sasl_username); string[length_username] = '\0'; } } else { /* sign the challenge with the private key and return the result */ /* decode the challenge */ data = malloc (strlen (data_base64) + 1); if (!data) return NULL; length_data = dogechat_string_decode_base64 (data_base64, data); /* read file with private key */ str_privkey = irc_sasl_get_key_content (server, sasl_key); if (!str_privkey) { free (data); return NULL; } /* import key */ gnutls_x509_privkey_init (&x509_privkey); gnutls_privkey_init (&privkey); filedatum.data = (unsigned char *)str_privkey; filedatum.size = strlen (str_privkey); ret = gnutls_x509_privkey_import (x509_privkey, &filedatum, GNUTLS_X509_FMT_PEM); free (str_privkey); if (ret != GNUTLS_E_SUCCESS) { dogechat_printf ( server->buffer, _("%sgnutls: invalid private key file: error %d %s"), dogechat_prefix ("error"), ret, gnutls_strerror (ret)); gnutls_x509_privkey_deinit (x509_privkey); gnutls_privkey_deinit (privkey); free (data); return NULL; } #if LIBGNUTLS_VERSION_NUMBER >= 0x030300 /* 3.3.0 */ /* read raw values in key, to display public key */ ret = gnutls_x509_privkey_export_ecc_raw (x509_privkey, &curve, &x, &y, &k); if (ret == GNUTLS_E_SUCCESS) { pubkey = malloc (x.size + 1); if (pubkey) { pubkey[0] = (y.data[y.size - 1] & 1) ? 0x03 : 0x02; memcpy (pubkey + 1, x.data, x.size); pubkey_base64 = malloc ((x.size + 1 + 1) * 4); if (pubkey_base64) { dogechat_string_encode_base64 (pubkey, x.size + 1, pubkey_base64); dogechat_printf ( server->buffer, _("%s%s: signing the challenge with ECC public key: " "%s"), dogechat_prefix ("network"), IRC_PLUGIN_NAME, pubkey_base64); free (pubkey_base64); } free (pubkey); } gnutls_free (x.data); gnutls_free (y.data); gnutls_free (k.data); } #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x030300 */ /* import private key in an abstract key structure */ ret = gnutls_privkey_import_x509 (privkey, x509_privkey, 0); /* gnutls >= 2.11.0 */ if (ret != GNUTLS_E_SUCCESS) { dogechat_printf ( server->buffer, _("%sgnutls: unable to import the private key: error %d %s"), dogechat_prefix ("error"), ret, gnutls_strerror (ret)); gnutls_x509_privkey_deinit (x509_privkey); gnutls_privkey_deinit (privkey); free (data); return NULL; } decoded_data.data = (unsigned char *)data; decoded_data.size = length_data; ret = gnutls_privkey_sign_hash (privkey, GNUTLS_DIG_SHA256, 0, /* gnutls >= 2.11.0 */ &decoded_data, &signature); if (ret != GNUTLS_E_SUCCESS) { dogechat_printf ( server->buffer, _("%sgnutls: unable to sign the hashed data: error %d %s"), dogechat_prefix ("error"), ret, gnutls_strerror (ret)); gnutls_x509_privkey_deinit (x509_privkey); gnutls_privkey_deinit (privkey); free (data); return NULL; } gnutls_x509_privkey_deinit (x509_privkey); gnutls_privkey_deinit (privkey); string = malloc (signature.size); if (string) memcpy (string, signature.data, signature.size); length = signature.size; gnutls_free (signature.data); free (data); } if (string && (length > 0)) { answer_base64 = malloc ((length + 1) * 4); if (answer_base64) dogechat_string_encode_base64 (string, length, answer_base64); free (string); } return answer_base64; #else /* no gnutls or gnutls < 3.0.21 */ /* make C compiler happy */ (void) data_base64; (void) sasl_username; (void) sasl_key; dogechat_printf (server->buffer, _("%sgnutls: version >= 3.0.21 is required for SASL " "\"ecdsa-nist256p-challenge\""), dogechat_prefix ("error")); return NULL; #endif /* defined(HAVE_GNUTLS) && (LIBGNUTLS_VERSION_NUMBER >= 0x030015) */ }
static int check_x509_privkey(void) { gnutls_x509_privkey_t key; gnutls_datum_t p, q, g, y, x; gnutls_datum_t m, e, u, e1, e2, d; gnutls_ecc_curve_t curve; int ret; global_init(); ret = gnutls_x509_privkey_init(&key); if (ret < 0) fail("error\n"); ret = gnutls_x509_privkey_import(key, &dsa_key, GNUTLS_X509_FMT_PEM); if (ret < 0) fail("error\n"); ret = gnutls_x509_privkey_export_dsa_raw(key, &p, &q, &g, &y, &x); if (ret < 0) fail("error\n"); CMP("p", &p, dsa_p); CMP("q", &q, dsa_q); CMP("g", &g, dsa_g); CMP("y", &y, dsa_y); CMP("x", &x, dsa_x); gnutls_free(p.data); gnutls_free(q.data); gnutls_free(g.data); gnutls_free(y.data); gnutls_free(x.data); gnutls_x509_privkey_deinit(key); /* RSA */ ret = gnutls_x509_privkey_init(&key); if (ret < 0) fail("error\n"); ret = gnutls_x509_privkey_import(key, &rsa_key, GNUTLS_X509_FMT_PEM); if (ret < 0) fail("error\n"); ret = gnutls_x509_privkey_export_rsa_raw2(key, &m, &e, &d, &p, &q, &u, &e1, &e2); if (ret < 0) fail("error\n"); CMP("m", &m, rsa_m); CMP("e", &e, rsa_e); CMP("d", &d, rsa_d); CMP("p", &p, rsa_p); CMP("q", &q, rsa_q); CMP("u", &u, rsa_u); CMP("e1", &e1, rsa_e1); CMP("e2", &e2, rsa_e2); gnutls_free(m.data); gnutls_free(e.data); gnutls_free(d.data); gnutls_free(p.data); gnutls_free(q.data); gnutls_free(u.data); gnutls_free(e1.data); gnutls_free(e2.data); gnutls_x509_privkey_deinit(key); /* ECC */ ret = gnutls_x509_privkey_init(&key); if (ret < 0) fail("error\n"); ret = gnutls_x509_privkey_import(key, &server_ecc_key, GNUTLS_X509_FMT_PEM); if (ret < 0) fail("error\n"); ret = gnutls_x509_privkey_export_ecc_raw(key, &curve, &x, &y, &p); if (ret < 0) fail("error\n"); if (curve != GNUTLS_ECC_CURVE_SECP256R1) { fprintf(stderr, "unexpected curve value: %d\n", (int)curve); exit(1); } CMP("x", &x, ecc_x); CMP("y", &y, ecc_y); CMP("k", &p, ecc_k); gnutls_free(x.data); gnutls_free(y.data); gnutls_free(p.data); gnutls_x509_privkey_deinit(key); return 0; }