static int generate_subkey( cdk_keygen_ctx_t hd ) { gcry_sexp_t s_params = NULL, s_key; size_t n = hd->key[1].len; int rc; if( !hd ) return CDK_Inv_Value; if( is_DSA( hd->key[1].algo) ) rc = gcry_sexp_build( &s_params, NULL, "(genkey(dsa(nbits %d)))", n ); else if( is_ELG( hd->key[1].algo) ) rc = gcry_sexp_build( &s_params, NULL, "(genkey(elg(nbits %d)))", n ); else if( is_RSA( hd->key[1].algo) ) rc = gcry_sexp_build( &s_params, NULL, "(genkey(rsa(nbits %d)))", n ); else rc = CDK_Inv_Algo; if( !rc ) rc = gcry_pk_genkey( &s_key, s_params ); gcry_sexp_release( s_params ); if( !rc ) { if( is_DSA( hd->key[1].algo) ) rc = read_dsa_key( s_key, hd->key[1].resarr ); else if( is_ELG( hd->key[1].algo) ) rc = read_elg_key( s_key, hd->key[1].resarr ); else if( is_RSA( hd->key[1].algo) ) rc = read_rsa_key( s_key, hd->key[1].resarr ); } hd->key[1].n = cdk_pk_get_npkey( hd->key[1].algo ); gcry_sexp_release( s_key ); return rc; }
static cdk_error_t pubenc_to_sexp (gcry_sexp_t * r_sexp, cdk_pkt_pubkey_enc_t enc) { gcry_sexp_t sexp = NULL; gcry_error_t err; const char *fmt; if (!r_sexp || !enc) return CDK_Inv_Value; *r_sexp = NULL; if (is_RSA (enc->pubkey_algo)) { fmt = "(enc-val(openpgp-rsa((a%m))))"; err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0]); } else if (is_ELG (enc->pubkey_algo)) { fmt = "(enc-val(openpgp-elg((a%m)(b%m))))"; err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0], enc->mpi[1]); } else return CDK_Inv_Algo; if (err) return map_gcry_error (err); *r_sexp = sexp; return 0; }
static cdk_error_t sig_to_sexp (gcry_sexp_t *r_sig_sexp, cdk_pkt_signature_t sig) { gcry_error_t err; cdk_error_t rc; const char *fmt; if (!r_sig_sexp || !sig) return CDK_Inv_Value; if (is_ELG (sig->pubkey_algo)) return CDK_Not_Implemented; rc = 0; if (is_RSA (sig->pubkey_algo)) { fmt = "(sig-val(openpgp-rsa(s%m)))"; err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0]); if (err) rc = map_gcry_error (err); } else if (is_DSA (sig->pubkey_algo)) { fmt = "(sig-val(openpgp-dsa(r%m)(s%m)))"; err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0], sig->mpi[1]); if (err) rc = map_gcry_error (err); } else rc = CDK_Inv_Algo; return rc; }
static cdk_error_t sexp_to_sig (cdk_pkt_signature_t sig, gcry_sexp_t sexp) { if (!sig || !sexp) return CDK_Inv_Value; /* ElGamal signatures are not supported any longer. */ if (is_ELG (sig->pubkey_algo)) { _cdk_log_debug ("sexp_to_sig: unsupported signature type (ElGamal)\n"); return CDK_Not_Implemented; } if (is_RSA (sig->pubkey_algo)) return sexp_to_mpi (sexp, "s", &sig->mpi[0]); else if (is_DSA (sig->pubkey_algo)) { cdk_error_t rc; rc = sexp_to_mpi (sexp, "r", &sig->mpi[0]); if (!rc) rc = sexp_to_mpi (sexp, "s", &sig->mpi[1]); return rc; } return CDK_Inv_Algo; }
/** * cdk_pk_get_nenc: * @algo: the public key algorithm * * Return the number of MPI's the encrypted data consists of. **/ int cdk_pk_get_nenc(int algo) { if (is_RSA(algo)) return 1; else if (is_ELG(algo)) return 2; else return 0; }
/** * cdk_pk_get_npkey: * @algo: The public key algorithm. * * Return the number of multiprecison integer forming an public * key with the given algorithm. */ int cdk_pk_get_npkey(int algo) { if (is_RSA(algo)) return RSA_PUBLIC_PARAMS; else if (is_DSA(algo)) return DSA_PUBLIC_PARAMS; else if (is_ELG(algo)) return 3; else { gnutls_assert(); return 0; } }
static cdk_error_t sexp_to_pubenc (cdk_pkt_pubkey_enc_t enc, gcry_sexp_t sexp) { if (!sexp || !enc) return CDK_Inv_Value; if (is_RSA (enc->pubkey_algo)) return sexp_to_mpi (sexp, "a", &enc->mpi[0]); else if (is_ELG (enc->pubkey_algo)) { cdk_error_t rc = sexp_to_mpi (sexp, "a", &enc->mpi[0]); if (!rc) rc = sexp_to_mpi (sexp, "b", &enc->mpi[1]); return rc; } return CDK_Inv_Algo; }
/** * cdk_keygen_start: kick off the key generation * @hd: the keygen object * **/ cdk_error_t cdk_keygen_start( cdk_keygen_ctx_t hd ) { gcry_sexp_t s_params = NULL, s_key = NULL; size_t n; int rc = 0; if( !hd || !hd->user_id ) return CDK_Inv_Value; if( is_ELG( hd->key[0].algo ) ) return CDK_Inv_Mode; if( !hd->key[0].len ) hd->key[0].len = 1024; n = hd->key[0].len; if( !hd->sym_prefs ) cdk_keygen_set_prefs( hd, CDK_PREFTYPE_SYM, NULL, 0 ); if( !hd->hash_prefs ) cdk_keygen_set_prefs( hd, CDK_PREFTYPE_HASH, NULL, 0 ); if( !hd->zip_prefs ) cdk_keygen_set_prefs( hd, CDK_PREFTYPE_ZIP, NULL, 0 ); if( is_DSA( hd->key[0].algo ) ) rc = gcry_sexp_build( &s_params, NULL, "(genkey(dsa(nbits %d)))", n ); else if( is_RSA( hd->key[0].algo ) ) rc = gcry_sexp_build( &s_params, NULL, "(genkey(rsa(nbits %d)))", n ); else rc = CDK_Inv_Algo; if( !rc ) rc = gcry_pk_genkey( &s_key, s_params ); gcry_sexp_release( s_params ); if( !rc ) { if( is_DSA( hd->key[0].algo ) ) rc = read_dsa_key( s_key, hd->key[0].resarr ); else if( is_RSA( hd->key[0].algo ) ) rc = read_rsa_key( s_key, hd->key[0].resarr ); hd->key[0].n = cdk_pk_get_npkey( hd->key[0].algo ); } gcry_sexp_release( s_key ); if( !rc ) { if( hd->key[1].algo && hd->key[1].len ) rc = generate_subkey( hd ); } return rc; }
/** * cdk_pk_get_nskey: * @algo: the public key algorithm * * Return the number of multiprecision integers forming an * secret key with the given algorithm. **/ int cdk_pk_get_nskey(int algo) { int ret; if (is_RSA(algo)) ret = RSA_PRIVATE_PARAMS - 2; /* we don't have exp1 and exp2 */ else if (is_DSA(algo)) ret = DSA_PRIVATE_PARAMS; else if (is_ELG(algo)) ret = 4; else { gnutls_assert(); return 0; } ret -= cdk_pk_get_npkey(algo); return ret; }
static int xml_add_key_mpi (gnutls_string * xmlkey, cdk_pkt_pubkey_t pk) { const char *s = " <KEY ENCODING=\"HEX\"/>\n"; int rc = 0; if (!xmlkey || !pk) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } _gnutls_string_append_str (xmlkey, s); if (is_RSA (pk->pubkey_algo)) { rc = xml_add_mpi (xmlkey, pk, 0, "RSA-N"); if (!rc) rc = xml_add_mpi (xmlkey, pk, 1, "RSA-E"); } else if (is_DSA (pk->pubkey_algo)) { rc = xml_add_mpi (xmlkey, pk, 0, "DSA-P"); if (!rc) rc = xml_add_mpi (xmlkey, pk, 1, "DSA-Q"); if (!rc) rc = xml_add_mpi (xmlkey, pk, 2, "DSA-G"); if (!rc) rc = xml_add_mpi (xmlkey, pk, 3, "DSA-Y"); } else if (is_ELG (pk->pubkey_algo)) { rc = xml_add_mpi (xmlkey, pk, 0, "ELG-P"); if (!rc) rc = xml_add_mpi (xmlkey, pk, 1, "ELG-G"); if (!rc) rc = xml_add_mpi (xmlkey, pk, 2, "ELG-Y"); } else return GNUTLS_E_UNWANTED_ALGORITHM; return 0; }
/* Convert the given secret key into a gcrypt SEXP object. */ static int seckey_to_sexp (gcry_sexp_t *r_skey, cdk_seckey_t sk) { gcry_sexp_t sexp = NULL; gcry_mpi_t *mpk = NULL, *msk = NULL; gcry_error_t err; cdk_pubkey_t pk; const char *fmt; if (!r_skey || !sk || !sk->pk) return CDK_Inv_Value; pk = sk->pk; mpk = pk->mpi; msk = sk->mpi; *r_skey = NULL; if (is_RSA (sk->pubkey_algo)) { fmt = "(private-key(openpgp-rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))"; err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1], msk[0], msk[1], msk[2], msk[3]); } else if (is_ELG (sk->pubkey_algo)) { fmt = "(private-key(openpgp-elg(p%m)(g%m)(y%m)(x%m)))"; err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1], mpk[2], msk[0]); } else if (is_DSA (sk->pubkey_algo)) { fmt = "(private-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)(x%m)))"; err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1], mpk[2], mpk[3], msk[0]); } else return CDK_Inv_Algo; if (err) return map_gcry_error (err); *r_skey = sexp; return 0; }
/* Convert the given public key to a gcrypt SEXP object. */ static cdk_error_t pubkey_to_sexp (gcry_sexp_t *r_key_sexp, cdk_pubkey_t pk) { gcry_mpi_t *m; gcry_error_t err; const char *fmt = NULL; cdk_error_t rc = 0; if (!r_key_sexp || !pk) return CDK_Inv_Value; m = pk->mpi; if (is_RSA (pk->pubkey_algo)) { fmt = "(public-key(openpgp-rsa(n%m)(e%m)))"; err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1]); if (err) rc = map_gcry_error (err); } else if (is_ELG (pk->pubkey_algo)) { fmt = "(public-key(openpgp-elg(p%m)(g%m)(y%m)))"; err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2]); if (err) rc = map_gcry_error (err); } else if (is_DSA (pk->pubkey_algo)) { fmt = "(public-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)))"; err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2], m[3]); if (err) rc = map_gcry_error (err); } else rc = CDK_Inv_Algo; return rc; }
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; }