GkmDataResult gkm_data_der_read_private_key_dsa_parts (const guchar *keydata, gsize n_keydata, const guchar *params, gsize n_params, gcry_sexp_t *s_key) { gcry_mpi_t p, q, g, y, x; GkmDataResult ret = GKM_DATA_UNRECOGNIZED; int res; GNode *asn_params = NULL; GNode *asn_key = NULL; p = q = g = y = x = NULL; asn_params = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", params, n_params); asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivatePart", keydata, n_keydata); if (!asn_params || !asn_key) goto done; ret = GKM_DATA_FAILURE; if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "p", NULL), &p) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "q", NULL), &q) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "g", NULL), &g)) goto done; if (!gkm_data_asn1_read_mpi (asn_key, &x)) goto done; /* Now we calculate y */ y = gcry_mpi_snew (1024); gcry_mpi_powm (y, g, x, p); res = gcry_sexp_build (s_key, NULL, SEXP_PRIVATE_DSA, p, q, g, y, x); if (res) goto done; g_assert (*s_key); ret = GKM_DATA_SUCCESS; done: egg_asn1x_destroy (asn_key); egg_asn1x_destroy (asn_params); gcry_mpi_release (p); gcry_mpi_release (q); gcry_mpi_release (g); gcry_mpi_release (y); gcry_mpi_release (x); if (ret == GKM_DATA_FAILURE) g_message ("invalid DSA key"); return ret; }
GkmDataResult gkm_data_der_read_public_key_dsa_parts (const guchar *keydata, gsize n_keydata, const guchar *params, gsize n_params, gcry_sexp_t *s_key) { gcry_mpi_t p, q, g, y; GkmDataResult ret = GKM_DATA_UNRECOGNIZED; GNode *asn_params = NULL; GNode *asn_key = NULL; int res; p = q = g = y = NULL; asn_params = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", params, n_params); asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPublicPart", keydata, n_keydata); if (!asn_params || !asn_key) goto done; ret = GKM_DATA_FAILURE; if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "p", NULL), &p) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "q", NULL), &q) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "g", NULL), &g)) goto done; if (!gkm_data_asn1_read_mpi (asn_key, &y)) goto done; res = gcry_sexp_build (s_key, NULL, SEXP_PUBLIC_DSA, p, q, g, y); if (res) goto done; g_assert (*s_key); ret = GKM_DATA_SUCCESS; done: egg_asn1x_destroy (asn_key); egg_asn1x_destroy (asn_params); gcry_mpi_release (p); gcry_mpi_release (q); gcry_mpi_release (g); gcry_mpi_release (y); if (ret == GKM_DATA_FAILURE) g_message ("invalid DSA key"); return ret; }
static GcrCertificateInfo* certificate_info_load (GcrCertificate *cert) { GcrCertificateInfo *info; GNode *asn1; gconstpointer der; gsize n_der; g_assert (GCR_IS_CERTIFICATE (cert)); der = gcr_certificate_get_der_data (cert, &n_der); g_return_val_if_fail (der, NULL); info = g_object_get_qdata (G_OBJECT (cert), CERTIFICATE_INFO); if (info != NULL) { if (n_der == info->n_der && der == info->der) return info; } /* Cache is invalid or non existent */ asn1 = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", der, n_der); if (asn1 == NULL) { g_warning ("a derived class provided an invalid or unparseable X.509 DER certificate data."); return NULL; } info = g_new0 (GcrCertificateInfo, 1); info->der = der; info->n_der = n_der; info->asn1 = asn1; g_object_set_qdata_full (G_OBJECT (cert), CERTIFICATE_INFO, info, certificate_info_free); return info; }
static GNode * cert_subject_public_key_from_attributes (GckAttributes *attributes) { const GckAttribute *attr; GBytes *bytes; GNode *cert; GNode *asn; attr = gck_attributes_find (attributes, CKA_VALUE); if (attr == NULL || gck_attribute_is_invalid (attr)) { _gcr_debug ("no value attribute for certificate"); return NULL; } bytes = g_bytes_new_with_free_func (attr->value, attr->length, gck_attributes_unref, gck_attributes_ref (attributes)); cert = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", bytes); g_bytes_unref (bytes); if (cert == NULL) { _gcr_debug ("couldn't parse certificate value"); return NULL; } asn = egg_asn1x_node (cert, "tbsCertificate", "subjectPublicKeyInfo", NULL); g_return_val_if_fail (asn != NULL, NULL); /* Remove the subject public key out of the certificate */ g_node_unlink (asn); egg_asn1x_destroy (cert); return asn; }
GkmDataResult gkm_data_der_read_enhanced_usage (const guchar *data, gsize n_data, GQuark **usage_oids) { GkmDataResult ret = GKM_DATA_UNRECOGNIZED; GNode *asn = NULL; GNode *node; GArray *array; GQuark oid; int i; asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "ExtKeyUsageSyntax", data, n_data); if (!asn) goto done; ret = GKM_DATA_FAILURE; array = g_array_new (TRUE, TRUE, sizeof (GQuark)); for (i = 0; TRUE; ++i) { node = egg_asn1x_node (asn, i + 1, NULL); if (node == NULL) break; oid = egg_asn1x_get_oid_as_quark (node); g_array_append_val (array, oid); } *usage_oids = (GQuark*)g_array_free (array, FALSE); ret = GKM_DATA_SUCCESS; done: egg_asn1x_destroy (asn); return ret; }
GkmDataResult gkm_data_der_read_certificate (const guchar *data, gsize n_data, GNode **asn1) { *asn1 = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data, n_data); if (!*asn1) return GKM_DATA_UNRECOGNIZED; return GKM_DATA_SUCCESS; }
GkmDataResult gkm_data_der_read_public_key_info (const guchar* data, gsize n_data, gcry_sexp_t* s_key) { GkmDataResult ret = GKM_DATA_UNRECOGNIZED; GQuark oid; GNode *asn = NULL; gsize n_params; guint n_bits; const guchar *params; guchar *key = NULL; init_quarks (); asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectPublicKeyInfo", data, n_data); if (!asn) goto done; ret = GKM_DATA_FAILURE; /* Figure out the algorithm */ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "algorithm", "algorithm", NULL)); if (!oid) goto done; /* A bit string so we cannot process in place */ key = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "subjectPublicKey", NULL), NULL, &n_bits); if (!key) goto done; /* An RSA key is simple */ if (oid == OID_PKIX1_RSA) { ret = gkm_data_der_read_public_key_rsa (key, n_bits / 8, s_key); /* A DSA key paramaters are stored separately */ } else if (oid == OID_PKIX1_DSA) { params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "algorithm", "parameters", NULL), &n_params); if (!params) goto done; ret = gkm_data_der_read_public_key_dsa_parts (key, n_bits / 8, params, n_params, s_key); } else { g_message ("unsupported key algorithm in certificate: %s", g_quark_to_string (oid)); ret = GKM_DATA_UNRECOGNIZED; goto done; } done: egg_asn1x_destroy (asn); g_free (key); if (ret == GKM_DATA_FAILURE) g_message ("invalid subject public-key info"); return ret; }
static void setup (Test *test, gconstpointer unused) { GBytes *data; gchar *contents; gsize length; if (!g_file_get_contents (SRCDIR "/pkcs11/gkm/fixtures/test-certificate-1.der", &contents, &length, NULL)) g_assert_not_reached (); data = g_bytes_new_take (contents, length); test->asn1_cert = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data); g_assert (test->asn1_cert); g_bytes_unref (data); }
static gchar* name_for_subject (const guchar *subject, gsize n_subject) { GNode *asn; gchar *name; g_assert (subject); g_assert (n_subject); asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Name", subject, n_subject); g_return_val_if_fail (asn, NULL); name = egg_dn_read_part (egg_asn1x_node (asn, "rdnSequence", NULL), "CN"); egg_asn1x_destroy (asn); return name; }
static guint calculate_dsa_params_size (gconstpointer data, gsize n_data) { GNode *asn; gsize n_content; asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", data, n_data); g_return_val_if_fail (asn, 0); if (!egg_asn1x_get_raw_value (egg_asn1x_node (asn, "p", NULL), &n_content)) g_return_val_if_reached (0); egg_asn1x_destroy (asn); /* Removes the complement */ return (n_content / 2) * 2 * 8; }
GkmDataResult gkm_data_der_read_private_key_dsa (GBytes *data, gcry_sexp_t *s_key) { gcry_mpi_t p, q, g, y, x; GkmDataResult ret = GKM_DATA_UNRECOGNIZED; int res; GNode *asn = NULL; p = q = g = y = x = NULL; asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivateKey", data); if (!asn) goto done; ret = GKM_DATA_FAILURE; if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "p", NULL), &p) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "q", NULL), &q) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "g", NULL), &g) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "Y", NULL), &y) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "priv", NULL), &x)) goto done; res = gcry_sexp_build (s_key, NULL, SEXP_PRIVATE_DSA, p, q, g, y, x); if (res) goto done; g_assert (*s_key); ret = GKM_DATA_SUCCESS; done: egg_asn1x_destroy (asn); gcry_mpi_release (p); gcry_mpi_release (q); gcry_mpi_release (g); gcry_mpi_release (y); gcry_mpi_release (x); if (ret == GKM_DATA_FAILURE) g_message ("invalid DSA key"); return ret; }
static void test_asn1_bit_string (Test *test, gconstpointer unused) { GNode *asn; GBytes *data; gboolean ret; GBytes *source, *target; gsize target_bits, source_bits; asn = egg_asn1x_create (test_asn1_tab, "TestBitString"); g_assert ("asn test structure is null" && asn != NULL); /* Create a string */ source = g_bytes_new (TEST_STRING, strlen(TEST_STRING)); g_return_if_fail (source); source_bits = g_bytes_get_size(source)*8; /* Write the string out */ ret = gkm_data_asn1_write_bit_string (egg_asn1x_node (asn, "data", NULL), source, source_bits); g_assert ("couldn't write string to asn1" && ret); /* Now encode the whole caboodle */ data = egg_asn1x_encode (asn, NULL); g_assert ("encoding asn1 didn't work" && data != NULL); egg_asn1x_destroy (asn); /* Now decode it all nicely */ asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestBitString", data); g_assert (asn != NULL); ret = gkm_data_asn1_read_bit_string (egg_asn1x_node (asn, "data", NULL), &target, &target_bits); egg_asn1x_destroy (asn); g_assert ("couldn't read bit string from asn1" && ret); g_assert ("bit string returned is null" && target != NULL); g_assert ("Source and target length differ" && target_bits == source_bits); g_assert ("Bit strings differ" && g_bytes_equal (source, target)); g_bytes_unref (data); g_bytes_unref (source); g_bytes_unref (target); }
GkmDataResult gkm_data_der_read_basic_constraints (GBytes *data, gboolean *is_ca, gint *path_len) { GkmDataResult ret = GKM_DATA_UNRECOGNIZED; GNode *asn = NULL; GNode *node; gulong value; asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "BasicConstraints", data); if (!asn) goto done; ret = GKM_DATA_FAILURE; if (path_len) { node = egg_asn1x_node (asn, "pathLenConstraint", NULL); if (!egg_asn1x_have (node)) *path_len = -1; else if (!egg_asn1x_get_integer_as_ulong (node, &value)) goto done; else *path_len = value; } if (is_ca) { node = egg_asn1x_node (asn, "cA", NULL); if (!egg_asn1x_have (node)) *is_ca = FALSE; else if (!egg_asn1x_get_boolean (node, is_ca)) goto done; } ret = GKM_DATA_SUCCESS; done: egg_asn1x_destroy (asn); if (ret == GKM_DATA_FAILURE) g_message ("invalid basic constraints"); return ret; }
static guint calculate_key_size (GcrCertificateInfo *info) { GNode *asn; gconstpointer data, params; gsize n_data, n_params; guint key_size = 0, n_bits; guchar *key = NULL; GQuark oid; data = egg_asn1x_get_raw_element (egg_asn1x_node (info->asn1, "tbsCertificate", "subjectPublicKeyInfo", NULL), &n_data); g_return_val_if_fail (data != NULL, 0); asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectPublicKeyInfo", data, n_data); g_return_val_if_fail (asn, 0); /* Figure out the algorithm */ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "algorithm", "algorithm", NULL)); g_return_val_if_fail (oid, 0); /* RSA keys are stored in the main subjectPublicKey field */ if (oid == OID_RSA_KEY) { /* A bit string so we cannot process in place */ key = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "subjectPublicKey", NULL), NULL, &n_bits); g_return_val_if_fail (key, 0); key_size = calculate_rsa_key_size (key, n_bits / 8); g_free (key); /* The DSA key size is discovered by the prime in params */ } else if (oid == OID_DSA_KEY) { params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "algorithm", "parameters", NULL), &n_params); key_size = calculate_dsa_params_size (params, n_params); } else { g_message ("unsupported key algorithm in certificate: %s", g_quark_to_string (oid)); } egg_asn1x_destroy (asn); return key_size; }
GkmDataResult gkm_data_der_read_public_key_dsa (const guchar *data, gsize n_data, gcry_sexp_t *s_key) { GkmDataResult ret = GKM_DATA_UNRECOGNIZED; GNode *asn = NULL; gcry_mpi_t p, q, g, y; int res; p = q = g = y = NULL; asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPublicKey", data, n_data); if (!asn) goto done; ret = GKM_DATA_FAILURE; if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "p", NULL), &p) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "q", NULL), &q) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "g", NULL), &g) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "Y", NULL), &y)) goto done; res = gcry_sexp_build (s_key, NULL, SEXP_PUBLIC_DSA, p, q, g, y); if (res) goto done; g_assert (*s_key); ret = GKM_DATA_SUCCESS; done: egg_asn1x_destroy (asn); gcry_mpi_release (p); gcry_mpi_release (q); gcry_mpi_release (g); gcry_mpi_release (y); if (ret == GKM_DATA_FAILURE) g_message ("invalid public DSA key"); return ret; }
static void test_asn1_integers (Test *test, gconstpointer unused) { GNode *asn; gcry_mpi_t mpi, mpt; GBytes *data; gboolean ret; asn = egg_asn1x_create (test_asn1_tab, "TestIntegers"); g_assert ("asn test structure is null" && asn != NULL); /* Make a random number */ mpi = gcry_mpi_new (512); g_return_if_fail (mpi); gcry_mpi_randomize (mpi, 512, GCRY_WEAK_RANDOM); /* Write the mpi out */ ret = gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "mpi", NULL), mpi); g_assert ("couldn't write mpi to asn1" && ret); /* Now encode the whole caboodle */ data = egg_asn1x_encode (asn, NULL); g_assert ("encoding asn1 didn't work" && data != NULL); egg_asn1x_destroy (asn); /* Now decode it all nicely */ asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestIntegers", data); g_assert (asn != NULL); ret = gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "mpi", NULL), &mpt); egg_asn1x_destroy (asn); g_assert ("couldn't read mpi from asn1" && ret); g_assert ("mpi returned is null" && mpt != NULL); g_assert ("mpi is wrong number" && gcry_mpi_cmp (mpi, mpt) == 0); g_bytes_unref (data); gcry_mpi_release (mpi); gcry_mpi_release (mpt); }
GkmDataResult gkm_data_der_read_key_usage (const guchar *data, gsize n_data, gulong *key_usage) { GkmDataResult ret = GKM_DATA_UNRECOGNIZED; GNode *asn = NULL; guint n_bits; asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "KeyUsage", data, n_data); if (!asn) goto done; ret = GKM_DATA_FAILURE; if (!egg_asn1x_get_bits_as_ulong (asn, key_usage, &n_bits)) goto done; ret = GKM_DATA_SUCCESS; done: egg_asn1x_destroy (asn); return ret; }
static guint calculate_rsa_key_size (GBytes *data) { GNode *asn; GBytes *content; guint key_size; asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPublicKey", data); g_return_val_if_fail (asn, 0); content = egg_asn1x_get_value_raw (egg_asn1x_node (asn, "modulus", NULL)); if (!content) g_return_val_if_reached (0); egg_asn1x_destroy (asn); /* Removes the complement */ key_size = (g_bytes_get_size (content) / 2) * 2 * 8; g_bytes_unref (content); return key_size; }
GkmDataResult gkm_data_der_read_public_key_rsa (GBytes *data, gcry_sexp_t *s_key) { GkmDataResult ret = GKM_DATA_UNRECOGNIZED; GNode *asn = NULL; gcry_mpi_t n, e; int res; n = e = NULL; asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPublicKey", data); if (!asn) goto done; ret = GKM_DATA_FAILURE; if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "modulus", NULL), &n) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "publicExponent", NULL), &e)) goto done; res = gcry_sexp_build (s_key, NULL, SEXP_PUBLIC_RSA, n, e); if (res) goto done; g_assert (*s_key); ret = GKM_DATA_SUCCESS; done: egg_asn1x_destroy (asn); gcry_mpi_release (n); gcry_mpi_release (e); if (ret == GKM_DATA_FAILURE) g_message ("invalid RSA public key"); return ret; }
static void test_asn1_oid (Test *test, gconstpointer unused) { GNode *asn; GBytes *data; gboolean ret; GQuark source, target; asn = egg_asn1x_create (test_asn1_tab, "TestOid"); g_assert ("asn test structure is null" && asn != NULL); /* Create a OID Quark */ OID_ANSI_SECP256R1 = g_quark_from_static_string("1.2.840.10045.3.1.7"); source = OID_ANSI_SECP256R1; /* Write the OID out */ ret = gkm_data_asn1_write_oid (egg_asn1x_node (asn, "oid", NULL), source); g_assert ("couldn't write OID to asn1" && ret); /* Now encode the whole caboodle */ data = egg_asn1x_encode (asn, NULL); g_assert ("encoding asn1 didn't work" && data != NULL); egg_asn1x_destroy (asn); /* Now decode it all nicely */ asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestOid", data); g_assert (asn != NULL); ret = gkm_data_asn1_read_oid (egg_asn1x_node (asn, "oid", NULL), &target); egg_asn1x_destroy (asn); g_assert ("couldn't read oid from asn1" && ret); g_assert ("oid returned is 0" && target != 0); g_assert ("mpi is wrong number" && source == target); g_bytes_unref (data); }
static void refresh_display (GcrCertificateDetailsWidget *self) { GtkTextIter start, iter; const guchar *data, *value; gsize n_data, n_value; const gchar *text; gulong version; guint index, size, n_bits; gchar *display; guchar *bits; GNode *asn; GQuark oid; GDate date; gtk_text_buffer_get_start_iter (self->pv->buffer, &start); gtk_text_buffer_get_end_iter (self->pv->buffer, &iter); gtk_text_buffer_delete (self->pv->buffer, &start, &iter); if (!self->pv->certificate) return; data = gcr_certificate_get_der_data (self->pv->certificate, &n_data); g_return_if_fail (data); asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data, n_data); g_return_if_fail (asn); /* The subject */ append_heading (self, _("Subject Name")); egg_dn_parse (egg_asn1x_node (asn, "tbsCertificate", "subject", "rdnSequence", NULL), on_parsed_dn_part, self); /* The Issuer */ append_heading (self, _("Issuer Name")); egg_dn_parse (egg_asn1x_node (asn, "tbsCertificate", "issuer", "rdnSequence", NULL), on_parsed_dn_part, self); /* The Issued Parameters */ append_heading (self, _("Issued Certificate")); if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "tbsCertificate", "version", NULL), &version)) g_return_if_reached (); display = g_strdup_printf ("%lu", version + 1); append_field_and_value (self, _("Version"), display, FALSE); g_free (display); value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "tbsCertificate", "serialNumber", NULL), &n_value); g_return_if_fail (value); display = egg_hex_encode_full (value, n_value, TRUE, ' ', 1); append_field_and_value (self, _("Serial Number"), display, TRUE); g_free (display); display = g_malloc0 (128); if (egg_asn1x_get_time_as_date (egg_asn1x_node (asn, "tbsCertificate", "validity", "notBefore", NULL), &date)) { if (!g_date_strftime (display, 128, "%Y-%m-%d", &date)) g_return_if_reached (); append_field_and_value (self, _("Not Valid Before"), display, FALSE); } if (egg_asn1x_get_time_as_date (egg_asn1x_node (asn, "tbsCertificate", "validity", "notAfter", NULL), &date)) { if (!g_date_strftime (display, 128, "%Y-%m-%d", &date)) g_return_if_reached (); append_field_and_value (self, _("Not Valid After"), display, FALSE); } g_free (display); /* Signature */ append_heading (self, _("Signature")); oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "signatureAlgorithm", "algorithm", NULL)); text = egg_oid_get_description (oid); append_field_and_value (self, _("Signature Algorithm"), text, FALSE); value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "signatureAlgorithm", "parameters", NULL), &n_value); if (value && n_value) { display = egg_hex_encode_full (value, n_value, TRUE, ' ', 1); append_field_and_value (self, _("Signature Parameters"), display, TRUE); g_free (display); } value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "signature", NULL), &n_value); g_return_if_fail (value); display = egg_hex_encode_full (value, n_value, TRUE, ' ', 1); append_field_and_value (self, _("Signature"), display, TRUE); g_free (display); /* Public Key Info */ append_heading (self, _("Public Key Info")); oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo", "algorithm", "algorithm", NULL)); text = egg_oid_get_description (oid); append_field_and_value (self, _("Key Algorithm"), text, FALSE); value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo", "algorithm", "parameters", NULL), &n_value); if (value && n_value) { display = egg_hex_encode_full (value, n_value, TRUE, ' ', 1); append_field_and_value (self, _("Key Parameters"), display, TRUE); g_free (display); } size = gcr_certificate_get_key_size (self->pv->certificate); if (size > 0) { display = g_strdup_printf ("%u", size); append_field_and_value (self, _("Key Size"), display, FALSE); g_free (display); } bits = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "tbsCertificate", "subjectPublicKeyInfo", "subjectPublicKey", NULL), NULL, &n_bits); g_return_if_fail (bits); display = egg_hex_encode_full (bits, n_bits / 8, TRUE, ' ', 1); append_field_and_value (self, _("Public Key"), display, TRUE); g_free (display); g_free (bits); /* Fingerprints */ append_heading (self, _("Fingerprints")); append_fingerprint (self, data, n_data, "SHA1", G_CHECKSUM_SHA1); append_fingerprint (self, data, n_data, "MD5", G_CHECKSUM_MD5); /* Extensions */ for (index = 1; TRUE; ++index) { if (!append_extension (self, asn, data, n_data, index)) break; } egg_asn1x_destroy (asn); }
GkmDataResult gkm_data_der_read_private_key_rsa (const guchar *data, gsize n_data, gcry_sexp_t *s_key) { GkmDataResult ret = GKM_DATA_UNRECOGNIZED; gcry_mpi_t n, e, d, p, q, u; gcry_mpi_t tmp; gulong version; GNode *asn = NULL; int res; n = e = d = p = q = u = NULL; asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPrivateKey", data, n_data); if (!asn) goto done; ret = GKM_DATA_FAILURE; if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), &version)) goto done; /* We only support simple version */ if (version != 0) { ret = GKM_DATA_UNRECOGNIZED; g_message ("unsupported version of RSA key: %lu", version); goto done; } if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "modulus", NULL), &n) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "publicExponent", NULL), &e) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "privateExponent", NULL), &d) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "prime1", NULL), &p) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "prime2", NULL), &q) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "coefficient", NULL), &u)) goto done; /* Fix up the incoming key so gcrypt likes it */ if (gcry_mpi_cmp (p, q) > 0) { /* P shall be smaller then Q! Swap primes. iqmp becomes u. */ tmp = p; p = q; q = tmp; } else { /* U needs to be recomputed. */ gcry_mpi_invm (u, p, q); } res = gcry_sexp_build (s_key, NULL, SEXP_PRIVATE_RSA, n, e, d, p, q, u); if (res) goto done; g_assert (*s_key); ret = GKM_DATA_SUCCESS; done: egg_asn1x_destroy (asn); gcry_mpi_release (n); gcry_mpi_release (e); gcry_mpi_release (d); gcry_mpi_release (p); gcry_mpi_release (q); gcry_mpi_release (u); if (ret == GKM_DATA_FAILURE) g_message ("invalid RSA key"); return ret; }
GkmDataResult gkm_data_der_read_private_pkcs8_crypted (const guchar *data, gsize n_data, const gchar *password, gsize n_password, gcry_sexp_t *s_key) { GNode *asn = NULL; gcry_cipher_hd_t cih = NULL; gcry_error_t gcry; GkmDataResult ret, r; GQuark scheme; guchar *crypted = NULL; const guchar *params; gsize n_crypted, n_params; gint l; init_quarks (); ret = GKM_DATA_UNRECOGNIZED; asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo", data, n_data); if (!asn) goto done; ret = GKM_DATA_FAILURE; /* Figure out the type of encryption */ scheme = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL)); if (!scheme) goto done; params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), &n_params); if (!params) goto done; /* * Parse the encryption stuff into a cipher. */ r = egg_symkey_read_cipher (scheme, password, n_password, params, n_params, &cih); if (r == GKM_DATA_UNRECOGNIZED) { ret = GKM_DATA_FAILURE; goto done; } else if (r != GKM_DATA_SUCCESS) { ret = r; goto done; } crypted = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "encryptedData", NULL), egg_secure_realloc, &n_crypted); if (!crypted) goto done; gcry = gcry_cipher_decrypt (cih, crypted, n_crypted, NULL, 0); gcry_cipher_close (cih); cih = NULL; if (gcry != 0) { g_warning ("couldn't decrypt pkcs8 data: %s", gcry_strerror (gcry)); goto done; } /* Unpad the DER data */ l = egg_asn1x_element_length (crypted, n_crypted); if (l <= 0 || l > n_crypted) { ret = GKM_DATA_LOCKED; goto done; } n_crypted = l; /* Try to parse the resulting key */ ret = gkm_data_der_read_private_pkcs8_plain (crypted, n_crypted, s_key); egg_secure_free (crypted); crypted = NULL; /* If unrecognized we assume bad password */ if (ret == GKM_DATA_UNRECOGNIZED) ret = GKM_DATA_LOCKED; done: if (cih) gcry_cipher_close (cih); egg_asn1x_destroy (asn); egg_secure_free (crypted); return ret; }
GkmDataResult gkm_data_der_read_private_pkcs8_plain (const guchar *data, gsize n_data, gcry_sexp_t *s_key) { GNode *asn = NULL; GkmDataResult ret; int algorithm; GQuark key_algo; const guchar *keydata; gsize n_keydata; const guchar *params; gsize n_params; ret = GKM_DATA_UNRECOGNIZED; init_quarks (); asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo", data, n_data); if (!asn) goto done; ret = GKM_DATA_FAILURE; algorithm = 0; key_algo = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "privateKeyAlgorithm", "algorithm", NULL)); if (!key_algo) goto done; else if (key_algo == OID_PKIX1_RSA) algorithm = GCRY_PK_RSA; else if (key_algo == OID_PKIX1_DSA) algorithm = GCRY_PK_DSA; if (!algorithm) { ret = GKM_DATA_UNRECOGNIZED; goto done; } keydata = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "privateKey", NULL), &n_keydata); if (!keydata) goto done; params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "privateKeyAlgorithm", "parameters", NULL), &n_params); ret = GKM_DATA_SUCCESS; done: if (ret == GKM_DATA_SUCCESS) { switch (algorithm) { case GCRY_PK_RSA: ret = gkm_data_der_read_private_key_rsa (keydata, n_keydata, s_key); break; case GCRY_PK_DSA: /* Try the normal one block format */ ret = gkm_data_der_read_private_key_dsa (keydata, n_keydata, s_key); /* Otherwise try the two part format that everyone seems to like */ if (ret == GKM_DATA_UNRECOGNIZED && params && n_params) ret = gkm_data_der_read_private_key_dsa_parts (keydata, n_keydata, params, n_params, s_key); break; default: g_message ("invalid or unsupported key type in PKCS#8 key"); ret = GKM_DATA_UNRECOGNIZED; break; }; } else if (ret == GKM_DATA_FAILURE) { g_message ("invalid PKCS#8 key"); } egg_asn1x_destroy (asn); return ret; }