static gconstpointer _gcr_certificate_get_subject_const (GcrCertificate *self, gsize *n_data) { GcrCertificateInfo *info; info = certificate_info_load (self); g_return_val_if_fail (info, NULL); return egg_asn1x_get_raw_element (egg_asn1x_node (info->asn1, "tbsCertificate", "subject", NULL), n_data); }
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 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 gboolean load_assertions (GkmXdgTrust *self, GNode *asn) { gconstpointer element; GHashTable *assertions; GkmAssertion *assertion; gsize n_element; GByteArray *key; GNode *node; guint count, i; g_assert (self); g_assert (asn); assertions = self->pv->assertions; self->pv->assertions = create_assertions (); count = egg_asn1x_count (egg_asn1x_node (asn, "assertions", NULL)); for (i = 0; i < count; ++i) { node = egg_asn1x_node (asn, "assertions", i + 1, NULL); g_return_val_if_fail (node, FALSE); /* We use the raw DER encoding as an assertion */ element = egg_asn1x_get_raw_element (node, &n_element); g_return_val_if_fail (node, FALSE); /* Double check that this is valid, because it's how we hash */ key = g_byte_array_new (); g_byte_array_append (key, element, n_element); /* Already have this assertion? */ assertion = g_hash_table_lookup (assertions, key); if (assertion) { if (!g_hash_table_steal (assertions, key)) g_assert_not_reached (); /* Create a new assertion */ } else { assertion = create_assertion (self, node); } add_assertion_to_trust (self, assertion, NULL); g_byte_array_unref (key); g_object_unref (assertion); } /* Override the stored assertions and netscape trust */ g_hash_table_remove_all (assertions); g_hash_table_unref (assertions); return TRUE; }
static CK_RV trust_get_complete (GkmXdgTrust *self, CK_ATTRIBUTE_PTR attr) { GNode *cert; gconstpointer element; gsize n_element; cert = egg_asn1x_node (self->pv->asn, "reference", "certComplete", NULL); g_return_val_if_fail (cert, CKR_GENERAL_ERROR); /* If it's not stored, then this attribute is not present */ if (!egg_asn1x_have (cert)) return CKR_ATTRIBUTE_TYPE_INVALID; element = egg_asn1x_get_raw_element (cert, &n_element); g_return_val_if_fail (element, CKR_GENERAL_ERROR); return gkm_attribute_set_data (attr, element, n_element); }
static CK_RV trust_get_der (GkmXdgTrust *self, const gchar *part, CK_ATTRIBUTE_PTR attr) { GNode *node; gconstpointer element; gsize n_element; g_assert (GKM_XDG_IS_TRUST (self)); node = egg_asn1x_node (self->pv->asn, "reference", "certReference", part, NULL); g_return_val_if_fail (node, CKR_GENERAL_ERROR); /* If the assertion doesn't contain this info ... */ if (!egg_asn1x_have (node)) return CKR_ATTRIBUTE_TYPE_INVALID; element = egg_asn1x_get_raw_element (node, &n_element); return gkm_attribute_set_data (attr, element, n_element); }
static void dump_certificate_complete (GNode *asn) { GNode *cert; gchar *issuer, *serial, *subject; gconstpointer element; gpointer data; gsize n_data, n_element; /* Parse the certificate out */ cert = egg_asn1x_create (pkix_asn1_tab, "Certificate"); g_return_if_fail (cert); element = egg_asn1x_get_raw_element (asn, &n_element); g_return_if_fail (element); if (!egg_asn1x_decode (cert, element, n_element)) barf_and_die ("couldn't parse certificate", egg_asn1x_message (cert)); issuer = egg_dn_read (egg_asn1x_node (asn, "issuer", NULL)); g_return_if_fail (issuer); subject = egg_dn_read (egg_asn1x_node (asn, "subject", NULL)); g_return_if_fail (subject); data = egg_asn1x_get_integer_as_raw (egg_asn1x_node (asn, "serial", NULL), NULL, &n_data); g_return_if_fail (data && n_data); serial = egg_hex_encode (data, n_data); g_free (data); g_print ("Complete\n"); g_print (" issuer: %s\n", issuer); g_print (" subject: %s\n", subject); g_print (" serial: 0x%s\n", serial); egg_asn1x_destroy (cert); g_free (data); g_free (serial); g_free (issuer); g_free (subject); }
static void dump_certificate_reference (GNode *asn) { gchar *issuer, *serial; gpointer data; gsize n_data; GNode *name; gconstpointer element; gsize n_element; /* Parse the name out */ name = egg_asn1x_create (pkix_asn1_tab, "Name"); g_return_if_fail (name); element = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "issuer", NULL), &n_element); g_return_if_fail (element); if (!egg_asn1x_decode (name, element, n_element)) barf_and_die ("couldn't parse certificate", egg_asn1x_message (name)); issuer = egg_dn_read (name); g_return_if_fail (issuer); data = egg_asn1x_get_integer_as_raw (egg_asn1x_node (asn, "serial", NULL), NULL, &n_data); g_return_if_fail (data && n_data); serial = egg_hex_encode (data, n_data); g_free (data); g_print ("Reference\n"); g_print (" issuer: %s\n", issuer); g_print (" serial: 0x%s\n", serial); egg_asn1x_destroy (name); g_free (data); g_free (serial); g_free (issuer); }
static CK_RV gkm_certificate_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE* attr) { GkmCertificate *self = GKM_CERTIFICATE (base); CK_ULONG category; const guchar *cdata; guchar *data; gsize n_data; time_t when; CK_RV rv; switch (attr->type) { case CKA_CLASS: return gkm_attribute_set_ulong (attr, CKO_CERTIFICATE); case CKA_PRIVATE: return gkm_attribute_set_bool (attr, FALSE); case CKA_LABEL: return gkm_attribute_set_string (attr, gkm_certificate_get_label (self)); case CKA_CERTIFICATE_TYPE: return gkm_attribute_set_ulong (attr, CKC_X_509); case CKA_TRUSTED: return gkm_attribute_set_bool (attr, FALSE); case CKA_CERTIFICATE_CATEGORY: if (!gkm_certificate_calc_category (self, session, &category)) return CKR_FUNCTION_FAILED; return gkm_attribute_set_ulong (attr, category); case CKA_CHECK_VALUE: g_return_val_if_fail (self->pv->data, CKR_GENERAL_ERROR); n_data = gcry_md_get_algo_dlen (GCRY_MD_SHA1); g_return_val_if_fail (n_data && n_data > 3, CKR_GENERAL_ERROR); data = g_new0 (guchar, n_data); gcry_md_hash_buffer (GCRY_MD_SHA1, data, self->pv->data, self->pv->n_data); rv = gkm_attribute_set_data (attr, data, 3); g_free (data); return rv; case CKA_START_DATE: case CKA_END_DATE: g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR); when = egg_asn1x_get_time_as_long (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "validity", attr->type == CKA_START_DATE ? "notBefore" : "notAfter", NULL)); if (when < 0) return CKR_FUNCTION_FAILED; return gkm_attribute_set_date (attr, when); case CKA_SUBJECT: g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR); cdata = egg_asn1x_get_raw_element (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "subject", NULL), &n_data); g_return_val_if_fail (cdata, CKR_GENERAL_ERROR); return gkm_attribute_set_data (attr, cdata, n_data); case CKA_ID: if (!self->pv->key) return gkm_attribute_set_data (attr, NULL, 0); return gkm_object_get_attribute (GKM_OBJECT (self->pv->key), session, attr); case CKA_ISSUER: g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR); cdata = egg_asn1x_get_raw_element (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "issuer", NULL), &n_data); g_return_val_if_fail (cdata, CKR_GENERAL_ERROR); return gkm_attribute_set_data (attr, cdata, n_data); case CKA_SERIAL_NUMBER: g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR); cdata = egg_asn1x_get_raw_element (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "serialNumber", NULL), &n_data); g_return_val_if_fail (cdata, CKR_GENERAL_ERROR); return gkm_attribute_set_data (attr, cdata, n_data); case CKA_VALUE: g_return_val_if_fail (self->pv->data, CKR_GENERAL_ERROR); return gkm_attribute_set_data (attr, self->pv->data, self->pv->n_data); /* These are only used for strange online certificates which we don't support */ case CKA_URL: case CKA_HASH_OF_SUBJECT_PUBLIC_KEY: case CKA_HASH_OF_ISSUER_PUBLIC_KEY: return gkm_attribute_set_data (attr, "", 0); /* What in the world is this doing in the spec? */ case CKA_JAVA_MIDP_SECURITY_DOMAIN: return gkm_attribute_set_ulong (attr, 0); /* 0 = unspecified */ }; return GKM_OBJECT_CLASS (gkm_certificate_parent_class)->get_attribute (base, session, attr); }
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; }