int crypto_cert_get_pub_exp_mod(CryptoCert cert, uint32 * key_len, uint8 * exponent, uint32 exp_len, uint8 * modulus, uint32 mod_len) { gnutls_datum_t m; gnutls_datum_t e; /* GnuTLS 2.10.1 contains patches for "MD5 with RSA Encryption" and "SHA with RSA Encryption" */ int x = gnutls_x509_crt_get_pk_rsa_raw(cert->cert, &m, &e); ASSERT(!x); *key_len = m.size; size_t l = e.size; ASSERT(l <= exp_len); memset(exponent, 0, exp_len - l); memcpy(exponent + exp_len - l, e.data, l); gnutls_free(e.data); l = m.size; ASSERT(l <= *key_len); memset(modulus, 0, *key_len - l); memcpy(modulus + *key_len - l, m.data, l); gnutls_free(m.data); return 0; }
gpg_err_code_t keyutil_get_cert_mpi ( unsigned char *der, size_t len, gcry_mpi_t *p_n_mpi, gcry_mpi_t *p_e_mpi ) { gpg_err_code_t error = GPG_ERR_GENERAL; gcry_mpi_t n_mpi = NULL; gcry_mpi_t e_mpi = NULL; #if defined(ENABLE_GNUTLS) gnutls_x509_crt_t cert = NULL; gnutls_datum_t datum = {der, len}; gnutls_datum_t m = {NULL, 0}, e = {NULL, 0}; #elif defined(ENABLE_OPENSSL) X509 *x509 = NULL; EVP_PKEY *pubkey = NULL; char *n_hex = NULL, *e_hex = NULL; #endif *p_n_mpi = NULL; *p_e_mpi = NULL; #if defined(ENABLE_GNUTLS) if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS) { cert = NULL; error = GPG_ERR_ENOMEM; goto cleanup; } if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) { error = GPG_ERR_BAD_CERT; goto cleanup; } if (gnutls_x509_crt_get_pk_rsa_raw (cert, &m, &e) != GNUTLS_E_SUCCESS) { error = GPG_ERR_BAD_KEY; m.data = NULL; e.data = NULL; goto cleanup; } if ( gcry_mpi_scan(&n_mpi, GCRYMPI_FMT_USG, m.data, m.size, NULL) || gcry_mpi_scan(&e_mpi, GCRYMPI_FMT_USG, e.data, e.size, NULL) ) { error = GPG_ERR_BAD_KEY; goto cleanup; } #elif defined(ENABLE_OPENSSL) if (!d2i_X509 (&x509, (my_openssl_d2i_t *)&der, len)) { error = GPG_ERR_BAD_CERT; goto cleanup; } if ((pubkey = X509_get_pubkey (x509)) == NULL) { error = GPG_ERR_BAD_CERT; goto cleanup; } if (pubkey->type != EVP_PKEY_RSA) { error = GPG_ERR_WRONG_PUBKEY_ALGO; goto cleanup; } n_hex = BN_bn2hex (pubkey->pkey.rsa->n); e_hex = BN_bn2hex (pubkey->pkey.rsa->e); if(n_hex == NULL || e_hex == NULL) { error = GPG_ERR_BAD_KEY; goto cleanup; } if ( gcry_mpi_scan (&n_mpi, GCRYMPI_FMT_HEX, n_hex, 0, NULL) || gcry_mpi_scan (&e_mpi, GCRYMPI_FMT_HEX, e_hex, 0, NULL) ) { error = GPG_ERR_BAD_KEY; goto cleanup; } #else #error Invalid configuration. #endif *p_n_mpi = n_mpi; n_mpi = NULL; *p_e_mpi = e_mpi; e_mpi = NULL; error = GPG_ERR_NO_ERROR; cleanup: if (n_mpi != NULL) { gcry_mpi_release (n_mpi); n_mpi = NULL; } if (e_mpi != NULL) { gcry_mpi_release (e_mpi); e_mpi = NULL; } #if defined(ENABLE_GNUTLS) if (m.data != NULL) { gnutls_free (m.data); m.data = NULL; } if (e.data != NULL) { gnutls_free (e.data); e.data = NULL; } if (cert != NULL) { gnutls_x509_crt_deinit (cert); cert = NULL; } #elif defined(ENABLE_OPENSSL) if (x509 != NULL) { X509_free (x509); x509 = NULL; } if (pubkey != NULL) { EVP_PKEY_free(pubkey); pubkey = NULL; } if (n_hex != NULL) { OPENSSL_free (n_hex); n_hex = NULL; } if (e_hex != NULL) { OPENSSL_free (e_hex); e_hex = NULL; } #else #error Invalid configuration. #endif return error; }
void __certificate_properties_fill_cert_subjectPublicKeyInfo (GtkTreeStore *store, GtkTreeIter *parent, gnutls_x509_crt_t *certificate) { int result; unsigned int bits = 0; const gchar * name = NULL; GtkTreeIter j; GtkTreeIter k; GtkTreeIter l; gchar *value; GtkTreeIter m; gnutls_datum_t modulus, publicExponent; gnutls_datum_t p, q, g, y; result = gnutls_x509_crt_get_pk_algorithm(*certificate, &bits); name = gnutls_pk_algorithm_get_name(result); gtk_tree_store_append(store, &j, parent); gtk_tree_store_set(store, &j, CERTIFICATE_PROPERTIES_COL_NAME, _("Subject Public Key Info"), -1); gtk_tree_store_append(store, &k, &j); gtk_tree_store_set(store, &k, CERTIFICATE_PROPERTIES_COL_NAME, _("Algorithm"), -1); gtk_tree_store_append(store, &l, &k); gtk_tree_store_set(store, &l, CERTIFICATE_PROPERTIES_COL_NAME, _("Algorithm"), CERTIFICATE_PROPERTIES_COL_VALUE, name, -1); switch (result) { case GNUTLS_PK_RSA: gtk_tree_store_append(store, &l, &k); gtk_tree_store_set(store, &l, CERTIFICATE_PROPERTIES_COL_NAME, _("Parameters"), CERTIFICATE_PROPERTIES_COL_VALUE, _("(unknown)"), -1); gtk_tree_store_append(store, &k, &j); gtk_tree_store_set(store, &k, CERTIFICATE_PROPERTIES_COL_NAME, _("RSA PublicKey"), -1); result = gnutls_x509_crt_get_pk_rsa_raw(*certificate, &modulus, &publicExponent); if (result < 0) { fprintf(stderr, "Error: (%s,%d): %s\n", __FILE__, __LINE__, gnutls_strerror(result)); break; } value = __certificate_properties_dump_raw_data(modulus.data, modulus.size); gnutls_free(modulus.data); gtk_tree_store_append(store, &l, &k); gtk_tree_store_set(store, &l, CERTIFICATE_PROPERTIES_COL_NAME, _("Modulus"), CERTIFICATE_PROPERTIES_COL_VALUE, value, -1); g_free(value); value = __certificate_properties_dump_raw_data(publicExponent.data, publicExponent.size); gnutls_free(publicExponent.data); gtk_tree_store_append(store, &l, &k); gtk_tree_store_set(store, &l, CERTIFICATE_PROPERTIES_COL_NAME, _("Public Exponent"), CERTIFICATE_PROPERTIES_COL_VALUE, value, -1); g_free(value); break; case GNUTLS_PK_DSA: result = gnutls_x509_crt_get_pk_dsa_raw(*certificate, &p, &q, &g, &y); if (result < 0) { fprintf(stderr, "Error: (%s,%d): %s\n", __FILE__, __LINE__, gnutls_strerror(result)); break; } gtk_tree_store_append(store, &l, &k); gtk_tree_store_set(store, &l, CERTIFICATE_PROPERTIES_COL_NAME, _("Parameters"), -1); value = __certificate_properties_dump_raw_data(p.data, p.size); gnutls_free(p.data); gtk_tree_store_append(store, &m, &l); gtk_tree_store_set(store, &m, CERTIFICATE_PROPERTIES_COL_NAME, "p", CERTIFICATE_PROPERTIES_COL_VALUE, value, -1); g_free(value); value = __certificate_properties_dump_raw_data(q.data, q.size); gnutls_free(q.data); gtk_tree_store_append(store, &m, &l); gtk_tree_store_set(store, &m, CERTIFICATE_PROPERTIES_COL_NAME, "p", CERTIFICATE_PROPERTIES_COL_VALUE, value, -1); g_free(value); value = __certificate_properties_dump_raw_data(g.data, g.size); gnutls_free(g.data); gtk_tree_store_append(store, &m, &l); gtk_tree_store_set(store, &m, CERTIFICATE_PROPERTIES_COL_NAME, "g", CERTIFICATE_PROPERTIES_COL_VALUE, value, -1); g_free(value); value = __certificate_properties_dump_raw_data(y.data, y.size); gnutls_free(y.data); gtk_tree_store_append(store, &k, &j); gtk_tree_store_set(store, &k, CERTIFICATE_PROPERTIES_COL_NAME, _("DSA PublicKey"), CERTIFICATE_PROPERTIES_COL_VALUE, value, -1); g_free(value); break; default: gtk_tree_store_append(store, &l, &k); gtk_tree_store_set(store, &l, CERTIFICATE_PROPERTIES_COL_NAME, _("Parameters"), CERTIFICATE_PROPERTIES_COL_VALUE, _("(unknown)"), -1); gtk_tree_store_append(store, &k, &j); gtk_tree_store_set(store, &k, CERTIFICATE_PROPERTIES_COL_NAME, _("Subject Public Key"), CERTIFICATE_PROPERTIES_COL_VALUE, _("(unknown)"), -1); break; } }
unsigned char *crypto_decrypt_signature(crypto_ctx *ctx, const unsigned char *sig_data, size_t sig_len, size_t *out_len, unsigned int padding, crypto_error **error) { unsigned char *buf = NULL, *rec_hash = NULL; gnutls_datum_t n = { NULL, 0 }, e = { NULL, 0 }; int err, algo; gcry_sexp_t key = NULL, sig = NULL, decrypted = NULL, child = NULL; gcry_mpi_t n_mpi = NULL, e_mpi = NULL, sig_mpi = NULL, dec_mpi = NULL; size_t buf_len = 0, hash_len = 0; if (!ctx) { crypto_error_set(error, 1, 0, "invalid crypto context"); return NULL; } if (!ctx->num) { crypto_error_set(error, 1, 0, "no certificates in the stack"); return NULL; } algo = gnutls_x509_crt_get_pk_algorithm(ctx->stack[ctx->num - 1], NULL); if (algo != GNUTLS_PK_RSA) { crypto_error_set(error, 1, 0, "certificate public key algorithm not RSA"); return NULL; } err = gnutls_x509_crt_get_pk_rsa_raw(ctx->stack[ctx->num - 1], &n, &e); if (err != GNUTLS_E_SUCCESS) { crypto_error_set(error, 1, 0, "error getting certificate public key"); return NULL; } err = gcry_mpi_scan(&n_mpi, GCRYMPI_FMT_USG, n.data, n.size, NULL); if (err) { crypto_error_set(error, 1, 0, "invalid RSA key 'n' format"); goto out; } err = gcry_mpi_scan(&e_mpi, GCRYMPI_FMT_USG, e.data, e.size, NULL); if (err) { crypto_error_set(error, 1, 0, "invalid RSA key 'e' format"); goto out; } err = gcry_sexp_build(&key, NULL, "(public-key (rsa (n %m) (e %m)))", n_mpi, e_mpi); if (err) { crypto_error_set(error, 1, 0, "could not create public-key expression"); goto out; } err = gcry_mpi_scan(&sig_mpi, GCRYMPI_FMT_USG, sig_data, sig_len, NULL); if (err) { crypto_error_set(error, 1, 0, "invalid signature format"); goto out; } err = gcry_sexp_build(&sig, NULL, "(data (flags raw) (value %m))", sig_mpi); if (err) { crypto_error_set(error, 1, 0, "could not create signature expression"); goto out; } /* encrypt is equivalent to public key decryption for RSA keys */ err = gcry_pk_encrypt(&decrypted, sig, key); if (err) { crypto_error_set(error, 1, 0, "could not decrypt signature"); goto out; } child = gcry_sexp_find_token(decrypted, "a", 1); if (!child) { crypto_error_set(error, 1, 0, "could not get decrypted signature result"); goto out; } dec_mpi = gcry_sexp_nth_mpi(child, 1, GCRYMPI_FMT_USG); gcry_sexp_release(child); if (!dec_mpi) { crypto_error_set(error, 1, 0, "could not get decrypted signature result"); goto out; } gcry_mpi_aprint(GCRYMPI_FMT_USG, &buf, &buf_len, dec_mpi); if (!buf) { crypto_error_set(error, 1, 0, "could not get extract decrypted signature"); goto out; } switch (padding) { case CRYPTO_PAD_NONE: rec_hash = buf; hash_len = buf_len; buf = NULL; *out_len = (int) hash_len; break; case CRYPTO_PAD_PKCS1: rec_hash = check_pkcs1_padding(buf, buf_len, &hash_len, error); if (!rec_hash) { crypto_error_set(error, 1, 0, "could not get extract decrypted padded signature"); goto out; } *out_len = (int) hash_len; break; default: crypto_error_set(error, 1, 0, "unknown padding mechanism %d", padding); break; } out: if (buf) free(buf); if (dec_mpi) gcry_mpi_release(dec_mpi); if (decrypted) gcry_sexp_release(decrypted); if (key) gcry_sexp_release(key); if (sig) gcry_sexp_release(sig); if (sig_mpi) gcry_mpi_release(sig_mpi); if (n_mpi) gcry_mpi_release(n_mpi); if (e_mpi) gcry_mpi_release(e_mpi); if (n.data) gcry_free(n.data); if (e.data) gcry_free(e.data); return rec_hash; }