void _gcr_display_view_append_fingerprint (GcrDisplayView *self, GcrRenderer *renderer, const guchar *data, gsize n_data, const gchar *name, GChecksumType type) { GChecksum *checksum; guint8 *buffer; gsize n_buffer; gchar *display; g_return_if_fail (GCR_IS_DISPLAY_VIEW (self)); checksum = g_checksum_new (type); g_return_if_fail (checksum); g_checksum_update (checksum, data, n_data); n_buffer = g_checksum_type_get_length (type); g_return_if_fail (n_buffer); buffer = g_malloc0 (n_buffer); g_checksum_get_digest (checksum, buffer, &n_buffer); g_checksum_free (checksum); display = egg_hex_encode_full (buffer, n_buffer, TRUE, ' ', 1); _gcr_display_view_append_value (self, renderer, name, display, TRUE); g_free (display); g_free (buffer); }
static gboolean parse_v3_rsa_bits_and_keyid (const guchar **at, const guchar *end, guint16 *bits, gchar **keyid) { guchar *n; gsize bytes; g_assert (bits); g_assert (keyid); /* Read in the modulus */ if (!read_mpi (at, end, bits, &n)) return FALSE; /* Last 64-bits of modulus are keyid */ bytes = (*bits + 7) / 8; if (bytes < 8) { g_free (n); return FALSE; } *keyid = egg_hex_encode_full (n + (bytes - 8), 8, TRUE, 0, 0); return TRUE; }
static void append_fingerprint (GcrCertificateDetailsWidget *self, const guchar *data, gsize n_data, const gchar *name, GChecksumType type) { GChecksum *checksum; guint8 *buffer; gsize n_buffer; gchar *display; checksum = g_checksum_new (type); g_return_if_fail (checksum); g_checksum_update (checksum, data, n_data); n_buffer = g_checksum_type_get_length (type); g_return_if_fail (n_buffer); buffer = g_malloc0 (n_buffer); g_checksum_get_digest (checksum, buffer, &n_buffer); g_checksum_free (checksum); display = egg_hex_encode_full (buffer, n_buffer, TRUE, ' ', 1); append_field_and_value (self, name, display, TRUE); g_free (display); g_free (buffer); }
static gchar * hash_v4_keyid (const guchar *data, const guchar *end, gchar **fingerprint) { gcry_md_hd_t mdh; gcry_error_t gcry; guchar header[3]; guint8 *digest; gchar *keyid; gsize len; /* * Both primary and subkeys use the public key tag byte * 0x99 to construct the hash. So we skip over that here. */ g_assert (data != NULL); g_assert (end > data); len = end - data; g_return_val_if_fail (len < G_MAXUSHORT, NULL); header[0] = 0x99; header[1] = len >> 8 & 0xff; header[2] = len & 0xff; gcry = gcry_md_open (&mdh, GCRY_MD_SHA1, 0); g_return_val_if_fail (gcry == 0, NULL); gcry_md_write (mdh, header, 3); gcry_md_write (mdh, data, len); digest = gcry_md_read (mdh, 0); keyid = egg_hex_encode_full (digest + 12, 8, TRUE, 0, 0); if (fingerprint) *fingerprint = egg_hex_encode_full (digest, 20, TRUE, 0, 0); gcry_md_close (mdh); return keyid; }
static gchar * hash_user_id_or_attribute (const guchar *beg, const guchar *end) { guint8 digest[20] = { 0, }; g_assert (beg != NULL); g_assert (end > beg); gcry_md_hash_buffer (GCRY_MD_RMD160, digest, beg, end - beg); return egg_hex_encode_full (digest, sizeof (digest), TRUE, 0, 0); }
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 parse_v3_signature (const guchar **at, const guchar *end, GcrOpenpgpParseFlags flags, GPtrArray *records) { guchar keyid[8]; guint8 sig_type; guint8 sig_len; guint32 sig_time; guint8 key_algo; guint8 hash_algo; guint16 left_bits; GcrRecord *record; gchar *value; if (!read_byte (at, end, &sig_len) || sig_len != 5) return FALSE; if (!read_byte (at, end, &sig_type) || !read_uint32 (at, end, &sig_time) || !read_bytes (at, end, keyid, 8) || !read_byte (at, end, &key_algo) || !read_byte (at, end, &hash_algo) || !read_uint16 (at, end, &left_bits) || !skip_signature_mpis (at, end, key_algo)) return FALSE; if (flags & GCR_OPENPGP_PARSE_SIGNATURES) { record = _gcr_record_new (GCR_RECORD_SCHEMA_SIG, GCR_RECORD_SIG_MAX, ':'); _gcr_record_set_uint (record, GCR_RECORD_SIG_ALGO, key_algo); value = egg_hex_encode_full (keyid, sizeof (keyid), TRUE, 0, 0); _gcr_record_take_raw (record, GCR_RECORD_SIG_KEYID, value); _gcr_record_set_ulong (record, GCR_RECORD_SIG_TIMESTAMP, sig_time); value = g_strdup_printf ("%02xx", (guint)sig_type); _gcr_record_take_raw (record, GCR_RECORD_SIG_CLASS, value); g_ptr_array_add (records, record); } return TRUE; }
/** * gcr_certificate_get_fingerprint_hex: * @self: a #GcrCertificate * @type: the type of algorithm for the fingerprint. * * Calculate the fingerprint for this certificate, and return it * as a hex string. * * You can pass G_CHECKSUM_SHA1 or G_CHECKSUM_MD5 as the @type * parameter. * * The caller should free the returned data using g_free() when * it is no longer required. * * Returns: an allocated hex string which contains the fingerprint. */ gchar* gcr_certificate_get_fingerprint_hex (GcrCertificate *self, GChecksumType type) { GChecksum *sum; guchar *digest; gsize n_digest; gssize length; gchar *hex; g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL); sum = digest_certificate (self, type); g_return_val_if_fail (sum, NULL); length = g_checksum_type_get_length (type); g_return_val_if_fail (length > 0, NULL); digest = g_malloc (length); n_digest = length; g_checksum_get_digest (sum, digest, &n_digest); hex = egg_hex_encode_full (digest, n_digest, TRUE, ' ', 1); g_checksum_free (sum); g_free (digest); return hex; }
static gboolean parse_v4_signature_revocation (const guchar **at, const guchar *end, GcrRecord *revocation) { guchar fingerprint[20]; gchar *value; guint8 klass; guint8 algo; if (!read_byte (at, end, &klass) || !read_byte (at, end, &algo) || !read_bytes (at, end, fingerprint, 20)) return FALSE; _gcr_record_set_uint (revocation, GCR_RECORD_RVK_ALGO, algo); value = egg_hex_encode_full (fingerprint, 20, TRUE, 0, 0); _gcr_record_take_raw (revocation, GCR_RECORD_RVK_FINGERPRINT, value); value = g_strdup_printf ("%02X", (guint)klass); _gcr_record_take_raw (revocation, GCR_RECORD_RVK_CLASS, value); return TRUE; }
gchar* egg_hex_encode (const guchar *data, gsize n_data) { return egg_hex_encode_full (data, n_data, TRUE, '\0', 0); }
static void dump_attribute_value (GckAttribute *attr) { gchar *data; gsize len; g_assert (attr->length != G_MAXULONG); if (attr->value == NULL) { g_printerr ("[null]"); return; } switch (attr->type) { case CKA_CLASS: if (attr->length == sizeof (CK_OBJECT_CLASS)) { dump_class_value (*(CK_ULONG_PTR)attr->value); return; } break; case CKA_X_ASSERTION_TYPE: if (attr->length == sizeof (CK_X_ASSERTION_TYPE)) { dump_assertion_type_value (*(CK_X_ASSERTION_TYPE*)attr->value); return; } break; case CKA_CERTIFICATE_TYPE: case CKA_CERTIFICATE_CATEGORY: case CKA_JAVA_MIDP_SECURITY_DOMAIN: case CKA_KEY_TYPE: case CKA_PRIME_BITS: case CKA_SUB_PRIME_BITS: case CKA_VALUE_BITS: case CKA_VALUE_LEN: case CKA_KEY_GEN_MECHANISM: case CKA_HW_FEATURE_TYPE: case CKA_PIXEL_X: case CKA_PIXEL_Y: case CKA_RESOLUTION: case CKA_CHAR_ROWS: case CKA_CHAR_COLUMNS: case CKA_BITS_PER_PIXEL: case CKA_MECHANISM_TYPE: case CKA_G_DESTRUCT_IDLE: case CKA_G_DESTRUCT_AFTER: case CKA_G_DESTRUCT_USES: case CKA_G_OBJECT: case CKA_G_CREDENTIAL: if (attr->length == sizeof (CK_ULONG)) { g_printerr ("%llu", (unsigned long long)*(CK_ULONG_PTR)attr->value); return; } break; case CKA_TOKEN: case CKA_PRIVATE: case CKA_TRUSTED: case CKA_SENSITIVE: case CKA_ENCRYPT: case CKA_DECRYPT: case CKA_WRAP: case CKA_UNWRAP: case CKA_SIGN: case CKA_SIGN_RECOVER: case CKA_VERIFY: case CKA_VERIFY_RECOVER: case CKA_DERIVE: case CKA_EXTRACTABLE: case CKA_LOCAL: case CKA_NEVER_EXTRACTABLE: case CKA_ALWAYS_SENSITIVE: case CKA_MODIFIABLE: case CKA_ALWAYS_AUTHENTICATE: case CKA_WRAP_WITH_TRUSTED: case CKA_RESET_ON_INIT: case CKA_HAS_RESET: case CKA_COLOR: case CKA_G_LOCKED: case CKA_G_LOGIN_COLLECTION: if (attr->length == sizeof (CK_BBOOL)) { g_printerr ("%s", (*(CK_BBOOL*)attr->value) ? "TRUE" : "FALSE"); return; } break; case CKA_LABEL: case CKA_URL: case CKA_CHAR_SETS: case CKA_ENCODING_METHODS: case CKA_MIME_TYPES: case CKA_G_COLLECTION: case CKA_G_SCHEMA: case CKA_X_PURPOSE: case CKA_X_PEER: if (g_utf8_validate (attr->value, attr->length, NULL)) { int length = MIN (32, attr->length); g_printerr ("%.*s%s", length, (gchar*)attr->value, length < attr->length ? "..." : ""); return; } break; case CKA_START_DATE: case CKA_END_DATE: case CKA_G_CREATED: case CKA_G_MODIFIED: if (attr->length == sizeof (CK_DATE)) { const CK_DATE* date = attr->value; g_printerr ("%.4s-%.2s-%.2s", date->year, date->month, date->day); return; } break; default: break; }; len = MIN (20, attr->length); data = egg_hex_encode_full (attr->value, len, TRUE, ':', 1); g_printerr ("%s%s", data, len < attr->length ? "..." : ""); g_free (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); }
static gboolean parse_v4_signature_subpacket (const guchar **at, const guchar *end, guint8 sub_type, GcrRecord *record, SigSubpacket *subpkt) { guchar keyid[8]; guint32 when; guint8 byte; gboolean critical; gchar *value; critical = (sub_type & 0x80) ? TRUE : FALSE; sub_type &= ~0xC0; switch (sub_type) { case OPENPGP_SIG_CREATION: if (!read_uint32 (at, end, &when)) return FALSE; _gcr_record_set_ulong (record, GCR_RECORD_SIG_TIMESTAMP, when); return TRUE; case OPENPGP_SIG_ISSUER: if (!read_bytes (at, end, keyid, 8)) return FALSE; value = egg_hex_encode_full (keyid, 8, TRUE, 0, 0); _gcr_record_take_raw (record, GCR_RECORD_SIG_KEYID, value); return TRUE; case OPENPGP_SIG_KEY_EXPIRY: if (!read_uint32 (at, end, &when)) return FALSE; subpkt->key_expiry = when; return TRUE; case OPENPGP_SIG_EXPIRY: if (!read_uint32 (at, end, &when)) return FALSE; _gcr_record_set_ulong (record, GCR_RECORD_SIG_EXPIRY, when); return TRUE; case OPENPGP_SIG_EXPORTABLE: if (!read_byte (at, end, &byte)) return FALSE; if (byte != 0 && byte != 1) return FALSE; subpkt->exportable = (byte == 0 ? FALSE : TRUE); return TRUE; case OPENPGP_SIG_PRIMARY_USERID: if (!read_byte (at, end, &byte)) return FALSE; if (byte != 0 && byte != 1) return FALSE; subpkt->primary = byte; return TRUE; case OPENPGP_SIG_KEY_FLAGS: if (!read_byte (at, end, &byte)) return FALSE; *at = end; /* N octets of flags */ subpkt->key_flags = byte; return TRUE; case OPENPGP_SIG_SIGNER_USERID: value = g_strndup ((gchar *)*at, end - *at); _gcr_record_set_string (record, GCR_RECORD_SIG_USERID, value); g_free (value); return TRUE; case OPENPGP_SIG_REVOCATION_KEY: _gcr_record_free (subpkt->revocation); subpkt->revocation = _gcr_record_new (GCR_RECORD_SCHEMA_RVK, GCR_RECORD_RVK_MAX, ':'); return parse_v4_signature_revocation (at, end, subpkt->revocation); /* Ignored */ case OPENPGP_SIG_SYMMETRIC_ALGOS: case OPENPGP_SIG_HASH_ALGOS: case OPENPGP_SIG_COMPRESSION_ALGOS: case OPENPGP_SIG_REVOCABLE: case OPENPGP_SIG_TRUST: case OPENPGP_SIG_REGULAR_EXPRESSION: case OPENPGP_SIG_NOTATION_DATA: case OPENPGP_SIG_KEYSERVER_PREFS: case OPENPGP_SIG_PREFERRED_KEYSERVER: case OPENPGP_SIG_POLICY_URI: case OPENPGP_SIG_REVOCATION_REASON: case OPENPGP_SIG_FEATURES: case OPENPGP_SIG_TARGET: case OPENPGP_SIG_EMBEDDED_SIGNATURE: *at = end; return TRUE; /* Unrecognized */ default: /* Critical, but not recognized */ if (critical) return FALSE; *at = end; return TRUE; } }