static void gkm_certificate_class_init (GkmCertificateClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass); gkm_certificate_parent_class = g_type_class_peek_parent (klass); g_type_class_add_private (klass, sizeof (GkmCertificatePrivate)); gobject_class->constructor = gkm_certificate_constructor; gobject_class->dispose = gkm_certificate_dispose; gobject_class->finalize = gkm_certificate_finalize; gobject_class->set_property = gkm_certificate_set_property; gobject_class->get_property = gkm_certificate_get_property; gkm_class->get_attribute = gkm_certificate_real_get_attribute; g_object_class_install_property (gobject_class, PROP_PUBLIC_KEY, g_param_spec_object ("public-key", "Public Key", "Public key contained in certificate", GKM_TYPE_CERTIFICATE_KEY, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, PROP_PUBLIC_KEY, g_param_spec_string ("label", "Label", "Label of the certificate", "", G_PARAM_READWRITE)); init_quarks (); }
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 gkm_xdg_trust_class_init (GkmXdgTrustClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass); GkmTrustClass *trust_class = GKM_TRUST_CLASS (klass); gobject_class->finalize = gkm_xdg_trust_finalize; gkm_class->get_attribute = gkm_xdg_trust_get_attribute; gkm_class->expose_object = gkm_xdg_trust_expose_object; trust_class->get_trust_level = gkm_xdg_trust_get_level; QDATA_ASSERTION_KEY = g_quark_from_static_string ("gkm-xdg-trust-assertion-key"); g_type_class_add_private (klass, sizeof (GkmXdgTrustPrivate)); init_quarks (); }
const char *quark(const char *str) { Array *bucket; char *value; size_t index; init_quarks(); bucket = quarks->items[hash_function(str, 0) % HASH_SIZE]; value = array_find_not(bucket, (array_item_predicate_t)strcmp, str); if (!value) { value = strdup(str); array_append(bucket, value); index = array_lower_bound(quarks_index, value, ptr_less); array_insert(quarks_index, index, value); } return value; }
static gcry_cipher_hd_t prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password, gsize n_password, gsize *n_block) { GNode *asn1_params = NULL; gcry_cipher_hd_t cih; guchar salt[8]; gcry_error_t gcry; guchar *key, *iv, *portion; gsize n_key, n_portion; int iterations; init_quarks (); /* Make sure the encryption algorithm works */ g_return_val_if_fail (gcry_cipher_algo_info (OID_PKCS12_PBE_3DES_SHA1, GCRYCTL_TEST_ALGO, NULL, 0), NULL); /* The encryption algorithm */ if(!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL), OID_PKCS12_PBE_3DES_SHA1)) g_return_val_if_reached (NULL); /* Randomize some input for the password based secret */ iterations = 1000 + (int) (1000.0 * rand () / (RAND_MAX + 1.0)); gcry_create_nonce (salt, sizeof (salt)); /* Allocate space for the key and iv */ n_key = gcry_cipher_get_algo_keylen (GCRY_CIPHER_3DES); *n_block = gcry_cipher_get_algo_blklen (GCRY_MD_SHA1); g_return_val_if_fail (n_key && *n_block, NULL); if (!egg_symkey_generate_pkcs12 (GCRY_CIPHER_3DES, GCRY_MD_SHA1, password, n_password, salt, sizeof (salt), iterations, &key, &iv)) g_return_val_if_reached (NULL); /* Now write out the parameters */ asn1_params = egg_asn1x_create (pkix_asn1_tab, "pkcs-12-PbeParams"); g_return_val_if_fail (asn1_params, NULL); if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn1_params, "salt", NULL), salt, sizeof (salt), NULL)) g_return_val_if_reached (NULL); if (!egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn1_params, "iterations", NULL), iterations)) g_return_val_if_reached (NULL); portion = egg_asn1x_encode (asn1_params, NULL, &n_portion); if (portion == NULL) { g_warning ("couldn't encode pkcs8 params key: %s", egg_asn1x_message (asn1_params)); g_return_val_if_reached (NULL); } if (!egg_asn1x_set_raw_element (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), portion, n_portion, g_free)) g_return_val_if_reached (NULL); /* Now make a cipher that matches what we wrote out */ gcry = gcry_cipher_open (&cih, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0); g_return_val_if_fail (gcry == 0, NULL); g_return_val_if_fail (cih, NULL); gcry_cipher_setiv (cih, iv, *n_block); gcry_cipher_setkey (cih, key, n_key); g_free (iv); egg_secure_free (key); egg_asn1x_destroy (asn1_params); return cih; }
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; }
guchar* gkm_data_der_write_private_pkcs8_plain (gcry_sexp_t skey, gsize *n_data) { GNode *asn = NULL; int algorithm; gboolean is_priv; GQuark oid; guchar *params, *key, *data; gsize n_params, n_key; init_quarks (); /* Parse and check that the key is for real */ if (!gkm_sexp_parse_key (skey, &algorithm, &is_priv, NULL)) g_return_val_if_reached (NULL); g_return_val_if_fail (is_priv == TRUE, NULL); asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo"); g_return_val_if_fail (asn, NULL); /* Write out the version */ if (!egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), 0)) g_return_val_if_reached (NULL); /* Per algorithm differences */ switch (algorithm) { /* RSA gets encoded in a standard simple way */ case GCRY_PK_RSA: oid = OID_PKIX1_RSA; params = NULL; n_params = 0; key = gkm_data_der_write_private_key_rsa (skey, &n_key); break; /* DSA gets incoded with the params seperate */ case GCRY_PK_DSA: oid = OID_PKIX1_DSA; key = gkm_data_der_write_private_key_dsa_part (skey, &n_key); params = gkm_data_der_write_private_key_dsa_params (skey, &n_params); break; default: g_warning ("trying to serialize unsupported private key algorithm: %d", algorithm); return NULL; }; /* Write out the algorithm */ if (!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "privateKeyAlgorithm", "algorithm", NULL), oid)) g_return_val_if_reached (NULL); /* Write out the parameters */ if (params) { if (!egg_asn1x_set_raw_element (egg_asn1x_node (asn, "privateKeyAlgorithm", "parameters", NULL), params, n_params, egg_secure_free)) g_return_val_if_reached (NULL); } /* Write out the key portion */ if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn, "privateKey", NULL), key, n_key, egg_secure_free)) g_return_val_if_reached (NULL); data = egg_asn1x_encode (asn, egg_secure_realloc, n_data); if (data == NULL) g_warning ("couldn't encode private pkcs8 key: %s", egg_asn1x_message (asn)); egg_asn1x_destroy (asn); return data; }
static gcry_cipher_hd_t prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password, gsize n_password, gsize *n_block) { GNode *asn1_params = NULL; gcry_cipher_hd_t cih; guchar *salt; gsize n_salt; gcry_error_t gcry; guchar *key, *iv; gsize n_key; int iterations; init_quarks (); /* Make sure the encryption algorithm works */ g_return_val_if_fail (gcry_cipher_algo_info (gcry_cipher_map_name (g_quark_to_string (OID_PKCS12_PBE_3DES_SHA1)), GCRYCTL_TEST_ALGO, NULL, 0) == 0, NULL); /* The encryption algorithm */ if(!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL), OID_PKCS12_PBE_3DES_SHA1)) g_return_val_if_reached (NULL); /* Randomize some input for the password based secret */ iterations = g_random_int_range (1000, 4096); n_salt = 8; salt = g_malloc (n_salt); gcry_create_nonce (salt, n_salt); /* Allocate space for the key and iv */ n_key = gcry_cipher_get_algo_keylen (GCRY_CIPHER_3DES); *n_block = gcry_cipher_get_algo_blklen (GCRY_MD_SHA1); g_return_val_if_fail (n_key && *n_block, NULL); if (!egg_symkey_generate_pkcs12 (GCRY_CIPHER_3DES, GCRY_MD_SHA1, password, n_password, salt, sizeof (salt), iterations, &key, &iv)) g_return_val_if_reached (NULL); /* Now write out the parameters */ asn1_params = egg_asn1x_create (pkix_asn1_tab, "pkcs-12-PbeParams"); g_return_val_if_fail (asn1_params, NULL); egg_asn1x_set_string_as_raw (egg_asn1x_node (asn1_params, "salt", NULL), salt, n_salt, g_free); egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn1_params, "iterations", NULL), iterations); egg_asn1x_set_any_from (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), asn1_params); /* Now make a cipher that matches what we wrote out */ gcry = gcry_cipher_open (&cih, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0); g_return_val_if_fail (gcry == 0, NULL); g_return_val_if_fail (cih, NULL); gcry_cipher_setiv (cih, iv, *n_block); gcry_cipher_setkey (cih, key, n_key); g_free (iv); egg_secure_free (key); egg_asn1x_destroy (asn1_params); return cih; }