static gint find_certificate_extension (GkmCertificate *self, GQuark oid) { GQuark exoid; GNode *node; guint index; g_assert (oid); g_assert (GKM_IS_CERTIFICATE (self)); g_assert (self->pv->asn1); for (index = 1; TRUE; ++index) { /* Make sure it is present */ node = egg_asn1x_node (self->pv->asn1, "tbsCertificate", "extensions", index, NULL); if (node == NULL) break; /* See if it's the same */ exoid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (node, "extnID", NULL)); if(exoid == oid) return index; } return 0; }
guint _gcr_subject_public_key_calculate_size (GNode *subject_public_key) { GBytes *key; GNode *params; guint key_size = 0; guint n_bits; GQuark oid; /* Figure out the algorithm */ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (subject_public_key, "algorithm", "algorithm", NULL)); g_return_val_if_fail (oid != 0, 0); /* RSA keys are stored in the main subjectPublicKey field */ if (oid == GCR_OID_PKIX1_RSA) { key = egg_asn1x_get_bits_as_raw (egg_asn1x_node (subject_public_key, "subjectPublicKey", NULL), &n_bits); g_return_val_if_fail (key != NULL, 0); key_size = calculate_rsa_key_size (key); g_bytes_unref (key); /* The DSA key size is discovered by the prime in params */ } else if (oid == GCR_OID_PKIX1_DSA) { params = egg_asn1x_node (subject_public_key, "algorithm", "parameters", NULL); key_size = calculate_dsa_params_size (params); } else { g_message ("unsupported key algorithm: %s", g_quark_to_string (oid)); } return key_size; }
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_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 gboolean append_extension (GcrCertificateDetailsWidget *self, GNode *asn, const guchar *data, gsize n_data, gint index) { GQuark oid; gchar *display; gsize n_value; const guchar *value; const gchar *text; gboolean critical; GNode *node; /* Make sure it is present */ asn = egg_asn1x_node (asn, "tbsCertificate", "extensions", index, NULL); if (asn == NULL) return FALSE; /* Dig out the OID */ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "extnID", NULL)); g_return_val_if_fail (oid, FALSE); append_heading (self, _("Extension")); /* Extension type */ text = egg_oid_get_description (oid); append_field_and_value (self, _("Identifier"), text, FALSE); /* Extension value */ value = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "extnValue", NULL), &n_value); /* TODO: Parsing of extensions that we understand */ display = egg_hex_encode_full (value, n_value, TRUE, ' ', 1); append_field_and_value (self, _("Value"), display, TRUE); g_free (display); /* Critical */ node = egg_asn1x_node (asn, "critical", NULL); if (node != NULL) { if (egg_asn1x_get_boolean (node, &critical)) append_field_and_value (self, _("Critical"), critical ? _("Yes") : _("No"), FALSE); } return TRUE; }
static gboolean prepare_subject_public_key_and_mechanisms (GcrCertificateRequest *self, GNode *subject_public_key, GQuark *algorithm, const gulong **mechanisms, gsize *n_mechanisms, GError **error) { GBytes *encoded; GNode *node; GQuark oid; g_assert (algorithm != NULL); g_assert (mechanisms != NULL); g_assert (n_mechanisms != NULL); encoded = egg_asn1x_encode (subject_public_key, NULL); g_return_val_if_fail (encoded != NULL, FALSE); node = egg_asn1x_node (subject_public_key, "algorithm", "algorithm", NULL); oid = egg_asn1x_get_oid_as_quark (node); if (oid == GCR_OID_PKIX1_RSA) { *mechanisms = RSA_MECHANISMS; *n_mechanisms = G_N_ELEMENTS (RSA_MECHANISMS); *algorithm = GCR_OID_PKIX1_SHA1_WITH_RSA; } else if (oid == GCR_OID_PKIX1_DSA) { *mechanisms = DSA_MECHANISMS; *n_mechanisms = G_N_ELEMENTS (DSA_MECHANISMS); *algorithm = GCR_OID_PKIX1_SHA1_WITH_DSA; } else { g_bytes_unref (encoded); g_set_error (error, GCR_DATA_ERROR, GCR_ERROR_UNRECOGNIZED, _("Unsupported key type for certificate request")); return FALSE; } node = egg_asn1x_node (self->asn, "certificationRequestInfo", "subjectPKInfo", NULL); if (!egg_asn1x_decode (node, encoded)) g_return_val_if_reached (FALSE); g_bytes_unref (encoded); return TRUE; }
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; }
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_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; }