/** * gnutls_openpgp_key_get_pk_algorithm - This function returns the key's PublicKey algorithm * @key: is an OpenPGP key * @bits: if bits is non null it will hold the size of the parameters' in bits * * This function will return the public key algorithm of an OpenPGP * certificate. * * If bits is non null, it should have enough size to hold the parameters * size in bits. For RSA the bits returned is the modulus. * For DSA the bits returned are of the public exponent. * * Returns a member of the GNUTLS_PKAlgorithm enumeration on success, * or a negative value on error. * **/ int gnutls_openpgp_key_get_pk_algorithm (gnutls_openpgp_key_t key, unsigned int *bits) { cdk_packet_t pkt; int algo = 0; if (!key) return GNUTLS_E_INVALID_REQUEST; pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); if (pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY) { if (bits) *bits = cdk_pk_get_nbits (pkt->pkt.public_key); algo = pkt->pkt.public_key->pubkey_algo; if (is_RSA (algo)) algo = GNUTLS_PK_RSA; else if (is_DSA (algo)) algo = GNUTLS_PK_DSA; else algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM; } return algo; }
/** * gnutls_openpgp_privkey_get_subkey_pk_algorithm: * @key: is an OpenPGP key * @idx: is the subkey index * @bits: if bits is non null it will hold the size of the parameters' in bits * * This function will return the public key algorithm of a subkey of an OpenPGP * certificate. * * If bits is non null, it should have enough size to hold the parameters * size in bits. For RSA the bits returned is the modulus. * For DSA the bits returned are of the public exponent. * * Returns: a member of the #gnutls_pk_algorithm_t enumeration on * success, or a negative error code on error. * * Since: 2.4.0 **/ gnutls_pk_algorithm_t gnutls_openpgp_privkey_get_subkey_pk_algorithm(gnutls_openpgp_privkey_t key, unsigned int idx, unsigned int *bits) { cdk_packet_t pkt; int algo; if (!key) { gnutls_assert(); return GNUTLS_PK_UNKNOWN; } if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) return gnutls_openpgp_privkey_get_pk_algorithm(key, bits); pkt = _get_secret_subkey(key, idx); algo = 0; if (pkt) { if (bits) *bits = cdk_pk_get_nbits(pkt->pkt.secret_key->pk); algo = pkt->pkt.secret_key->pubkey_algo; if (is_RSA(algo)) algo = GNUTLS_PK_RSA; else if (is_DSA(algo)) algo = GNUTLS_PK_DSA; else algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM; } return algo; }
/** * cdk_pk_sign: * @sk: secret key * @sig: signature * @md: the message digest * * Sign the message digest from @md and write the result into @sig. **/ cdk_error_t cdk_pk_sign (cdk_seckey_t sk, cdk_pkt_signature_t sig, const byte *md) { gcry_sexp_t s_skey = NULL, s_sig = NULL, s_hash = NULL; byte *encmd = NULL; size_t enclen = 0; int nbits; cdk_error_t rc; gcry_error_t err; if (!sk || !sk->pk || !sig || !md) return CDK_Inv_Value; if (!is_unprotected (sk)) return CDK_Inv_Mode; if (!KEY_CAN_SIGN (sig->pubkey_algo)) return CDK_Inv_Algo; nbits = cdk_pk_get_nbits (sk->pk); rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, sk->pk->pubkey_algo, md, sig->digest_algo, nbits); if (rc) return rc; rc = seckey_to_sexp (&s_skey, sk); if (!rc) rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen); if (rc) { cdk_free (encmd); gcry_sexp_release (s_skey); return rc; } err = gcry_pk_sign (&s_sig, s_hash, s_skey); if (err) rc = map_gcry_error (err); else { rc = sexp_to_sig (sig, s_sig); if (!rc) { sig->digest_start[0] = md[0]; sig->digest_start[1] = md[1]; } } gcry_sexp_release (s_skey); gcry_sexp_release (s_hash); gcry_sexp_release (s_sig); cdk_free (encmd); return rc; }
/** * cdk_pklist_encrypt: * @pkl: the keylist * @dek: the data encryption key * @outp: the stream to write in the data * * Encrypt the session key with each key of the list and wrap it * into a PUBKEY_ENC packet and write it to @outp. */ cdk_error_t cdk_pklist_encrypt( cdk_keylist_t pk_list, cdk_dek_t dek, cdk_stream_t outp ) { cdk_pkt_pubkey_t pk = NULL; cdk_pkt_pubkey_enc_t enc = NULL; cdk_packet_t pkt; cdk_sesskey_t frame = NULL; int nbits = 0; int rc = 0; if( !pk_list || !dek || !outp ) return CDK_Inv_Value; if( pk_list->type != CDK_PKT_PUBLIC_KEY ) return CDK_Inv_Mode; pkt = cdk_calloc( 1, sizeof * pkt ); if( !pkt ) return CDK_Out_Of_Core; for( ; pk_list; pk_list = pk_list->next ) { pk = pk_list->key.pk; cdk_free( enc ); enc = cdk_calloc( 1, sizeof *enc ); if( !enc ) return CDK_Out_Of_Core; enc->version = 3; enc->pubkey_algo = pk->pubkey_algo; cdk_pk_get_keyid( pk, enc->keyid ); nbits = cdk_pk_get_nbits( pk ); rc = cdk_dek_encode_pkcs1( dek, nbits, &frame ); if( rc ) break; rc = cdk_pk_encrypt( pk, enc, frame ); cdk_sesskey_free( frame ); if( rc ) break; else { cdk_pkt_init( pkt ); pkt->old_ctb = dek->rfc1991? 1 : 0; pkt->pkttype = CDK_PKT_PUBKEY_ENC; pkt->pkt.pubkey_enc = enc; rc = cdk_pkt_write( outp, pkt ); cdk_pkt_free( pkt ); if( rc ) break; } } cdk_free( pkt ); cdk_free( enc ); return rc; }
/** * gnutls_openpgp_privkey_get_pk_algorithm: * @key: is an OpenPGP key * @bits: if bits is non null it will hold the size of the parameters' in bits * * This function will return the public key algorithm of an OpenPGP * certificate. * * If bits is non null, it should have enough size to hold the parameters * size in bits. For RSA the bits returned is the modulus. * For DSA the bits returned are of the public exponent. * * Returns: a member of the #gnutls_pk_algorithm_t enumeration on * success, or a negative error code on error. * * Since: 2.4.0 **/ gnutls_pk_algorithm_t gnutls_openpgp_privkey_get_pk_algorithm (gnutls_openpgp_privkey_t key, unsigned int *bits) { cdk_packet_t pkt; int algo = 0, ret; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; if (!key) { gnutls_assert (); return GNUTLS_PK_UNKNOWN; } ret = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid); if (ret == 0) { int idx; idx = gnutls_openpgp_privkey_get_subkey_idx (key, keyid); if (idx != GNUTLS_OPENPGP_MASTER_KEYID_IDX) { algo = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, idx, bits); return algo; } } pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); if (pkt) { if (bits) *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk); algo = _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo); } return algo; }
/** * cdk_pk_verify: * @pk: the public key * @sig: signature * @md: the message digest * * Verify the signature in @sig and compare it with the message digest in @md. **/ cdk_error_t cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte *md) { gcry_sexp_t s_pkey = NULL, s_sig = NULL, s_hash = NULL; byte *encmd = NULL; size_t enclen; cdk_error_t rc; if (!pk || !sig || !md) return CDK_Inv_Value; rc = pubkey_to_sexp (&s_pkey, pk); if (rc) return rc; rc = sig_to_sexp (&s_sig, sig); if (rc) goto leave; rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, pk->pubkey_algo, md, sig->digest_algo, cdk_pk_get_nbits (pk)); if (rc) goto leave; rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen); if (rc) goto leave; if (gcry_pk_verify (s_sig, s_hash, s_pkey)) rc = CDK_Bad_Sig; leave: gcry_sexp_release (s_sig); gcry_sexp_release (s_hash); gcry_sexp_release (s_pkey); cdk_free (encmd); return rc; }
/** * gnutls_openpgp_privkey_get_pk_algorithm: * @key: is an OpenPGP key * @bits: if bits is non null it will hold the size of the parameters' in bits * * This function will return the public key algorithm of an OpenPGP * certificate. * * If bits is non null, it should have enough size to hold the parameters * size in bits. For RSA the bits returned is the modulus. * For DSA the bits returned are of the public exponent. * * Returns: a member of the #gnutls_pk_algorithm_t enumeration on * success, or a negative value on error. * * Since: 2.4.0 **/ gnutls_pk_algorithm_t gnutls_openpgp_privkey_get_pk_algorithm (gnutls_openpgp_privkey_t key, unsigned int *bits) { cdk_packet_t pkt; int algo; if (!key) { gnutls_assert (); return GNUTLS_PK_UNKNOWN; } algo = 0; pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); if (pkt) { if (bits) *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk); algo = _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo); } return algo; }
static int xml_add_key (gnutls_string * xmlkey, int ext, cdk_pkt_pubkey_t pk, int sub) { const char *algo, *s; char keyid[16], fpr[41], tmp[32]; uint8_t fingerpr[20]; unsigned int kid[2]; int i = 0, rc = 0; if (!xmlkey || !pk) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } s = sub ? " <SUBKEY>\n" : " <MAINKEY>\n"; _gnutls_string_append_str (xmlkey, s); cdk_pk_get_keyid (pk, kid); snprintf (keyid, 16, "%08lX%08lX", kid[0], kid[1]); rc = xml_add_tag (xmlkey, "KEYID", keyid); if (rc) return rc; cdk_pk_get_fingerprint (pk, fingerpr); for (i = 0; i < 20; i++) sprintf (fpr + 2 * i, "%02X", fingerpr[i]); fpr[40] = '\0'; rc = xml_add_tag (xmlkey, "FINGERPRINT", fpr); if (rc) return rc; if (is_DSA (pk->pubkey_algo)) algo = "DSA"; else if (is_RSA (pk->pubkey_algo)) algo = "RSA"; else if (is_ELG (pk->pubkey_algo)) algo = "ELG"; else algo = "???"; rc = xml_add_tag (xmlkey, "PKALGO", algo); if (rc) return rc; sprintf (tmp, "%d", cdk_pk_get_nbits (pk)); rc = xml_add_tag (xmlkey, "KEYLEN", tmp); if (rc) return rc; sprintf (tmp, "%lu", pk->timestamp); rc = xml_add_tag (xmlkey, "CREATED", tmp); if (rc) return rc; if (pk->expiredate > 0) { sprintf (tmp, "%lu", (unsigned long) pk->expiredate); rc = xml_add_tag (xmlkey, "EXPIREDATE", tmp); if (rc) return rc; } sprintf (tmp, "%d", pk->is_revoked); rc = xml_add_tag (xmlkey, "REVOKED", tmp); if (rc) return rc; if (ext) { rc = xml_add_key_mpi (xmlkey, pk); if (rc) return rc; } s = sub ? " </SUBKEY>\n" : " </MAINKEY>\n"; _gnutls_string_append_str (xmlkey, s); return 0; }
/** * cdk_pk_verify: * @pk: the public key * @sig: signature * @md: the message digest * * Verify the signature in @sig and compare it with the message digest in @md. **/ cdk_error_t cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md) { gnutls_datum_t s_sig; byte *encmd = NULL; size_t enclen; cdk_error_t rc; int ret, algo; unsigned int i; gnutls_datum_t data; gnutls_pk_params_st params; if (!pk || !sig || !md) { gnutls_assert (); return CDK_Inv_Value; } if (is_DSA (pk->pubkey_algo)) algo = GNUTLS_PK_DSA; else if (is_RSA (pk->pubkey_algo)) algo = GNUTLS_PK_RSA; else { gnutls_assert (); return CDK_Inv_Value; } rc = sig_to_datum (&s_sig, sig); if (rc) { gnutls_assert (); goto leave; } rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, pk->pubkey_algo, md, sig->digest_algo, cdk_pk_get_nbits (pk)); if (rc) { gnutls_assert (); goto leave; } data.data = encmd; data.size = enclen; params.params_nr = cdk_pk_get_npkey (pk->pubkey_algo); for (i = 0; i < params.params_nr; i++) params.params[i] = pk->mpi[i]; params.flags = 0; ret = _gnutls_pk_verify (algo, &data, &s_sig, ¶ms); if (ret < 0) { gnutls_assert (); rc = map_gnutls_error (ret); goto leave; } rc = 0; leave: _gnutls_free_datum (&s_sig); cdk_free (encmd); return rc; }