/* add a key to a secret keyring */ int __ops_add_to_secring(__ops_keyring_t *keyring, const __ops_seckey_t *seckey) { const __ops_pubkey_t *pubkey; __ops_key_t *key; if (__ops_get_debug_level(__FILE__)) { fprintf(stderr, "__ops_add_to_secring\n"); } if (keyring->keyc > 0) { key = &keyring->keys[keyring->keyc - 1]; if (__ops_get_debug_level(__FILE__) && key->key.pubkey.alg == OPS_PKA_DSA && seckey->pubkey.alg == OPS_PKA_ELGAMAL) { fprintf(stderr, "__ops_add_to_secring: found elgamal seckey\n"); } } EXPAND_ARRAY(keyring, key); key = &keyring->keys[keyring->keyc++]; (void) memset(key, 0x0, sizeof(*key)); pubkey = &seckey->pubkey; __ops_keyid(key->sigid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype); __ops_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype); key->type = OPS_PTAG_CT_SECRET_KEY; key->key.seckey = *seckey; if (__ops_get_debug_level(__FILE__)) { fprintf(stderr, "__ops_add_to_secring: keyc %u\n", keyring->keyc); } return 1; }
/* add a key to a public keyring */ int __ops_add_to_pubring(__ops_keyring_t *keyring, const __ops_pubkey_t *pubkey, __ops_content_enum tag) { __ops_key_t *key; time_t duration; if (__ops_get_debug_level(__FILE__)) { fprintf(stderr, "__ops_add_to_pubring (type %u)\n", tag); } switch(tag) { case OPS_PTAG_CT_PUBLIC_KEY: EXPAND_ARRAY(keyring, key); key = &keyring->keys[keyring->keyc++]; duration = key->key.pubkey.duration; (void) memset(key, 0x0, sizeof(*key)); key->type = tag; __ops_keyid(key->sigid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype); __ops_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype); key->key.pubkey = *pubkey; key->key.pubkey.duration = duration; return 1; case OPS_PTAG_CT_PUBLIC_SUBKEY: /* subkey is not the first */ key = &keyring->keys[keyring->keyc - 1]; __ops_keyid(key->encid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype); duration = key->key.pubkey.duration; (void) memcpy(&key->enckey, pubkey, sizeof(key->enckey)); key->enckey.duration = duration; return 1; default: return 0; } }
/** \ingroup HighLevel_KeyGenerate \brief Generates an RSA keypair \param numbits Modulus size \param e Public Exponent \param keydata Pointer to keydata struct to hold new key \return 1 if key generated successfully; otherwise 0 \note It is the caller's responsibility to call __ops_keydata_free(keydata) */ static unsigned rsa_generate_keypair(__ops_key_t *keydata, const int numbits, const unsigned long e, const char *hashalg, const char *cipher) { __ops_seckey_t *seckey; RSA *rsa; BN_CTX *ctx; __ops_output_t *output; __ops_memory_t *mem; ctx = BN_CTX_new(); __ops_keydata_init(keydata, OPS_PTAG_CT_SECRET_KEY); seckey = __ops_get_writable_seckey(keydata); /* generate the key pair */ rsa = RSA_generate_key(numbits, e, NULL, NULL); /* populate __ops key from ssl key */ seckey->pubkey.version = OPS_V4; seckey->pubkey.birthtime = time(NULL); seckey->pubkey.days_valid = 0; seckey->pubkey.alg = OPS_PKA_RSA; seckey->pubkey.key.rsa.n = BN_dup(rsa->n); seckey->pubkey.key.rsa.e = BN_dup(rsa->e); seckey->s2k_usage = OPS_S2KU_ENCRYPTED_AND_HASHED; seckey->s2k_specifier = OPS_S2KS_SALTED; /* seckey->s2k_specifier=OPS_S2KS_SIMPLE; */ if ((seckey->hash_alg = __ops_str_to_hash_alg(hashalg)) == OPS_HASH_UNKNOWN) { seckey->hash_alg = OPS_HASH_SHA1; } seckey->alg = __ops_str_to_cipher(cipher); seckey->octetc = 0; seckey->checksum = 0; seckey->key.rsa.d = BN_dup(rsa->d); seckey->key.rsa.p = BN_dup(rsa->p); seckey->key.rsa.q = BN_dup(rsa->q); seckey->key.rsa.u = BN_mod_inverse(NULL, rsa->p, rsa->q, ctx); if (seckey->key.rsa.u == NULL) { (void) fprintf(stderr, "seckey->key.rsa.u is NULL\n"); return 0; } BN_CTX_free(ctx); RSA_free(rsa); __ops_keyid(keydata->sigid, OPS_KEY_ID_SIZE, &keydata->key.seckey.pubkey, seckey->hash_alg); __ops_fingerprint(&keydata->sigfingerprint, &keydata->key.seckey.pubkey, seckey->hash_alg); /* Generate checksum */ output = NULL; mem = NULL; __ops_setup_memory_write(&output, &mem, 128); __ops_push_checksum_writer(output, seckey); switch (seckey->pubkey.alg) { case OPS_PKA_DSA: return __ops_write_mpi(output, seckey->key.dsa.x); case OPS_PKA_RSA: case OPS_PKA_RSA_ENCRYPT_ONLY: case OPS_PKA_RSA_SIGN_ONLY: if (!__ops_write_mpi(output, seckey->key.rsa.d) || !__ops_write_mpi(output, seckey->key.rsa.p) || !__ops_write_mpi(output, seckey->key.rsa.q) || !__ops_write_mpi(output, seckey->key.rsa.u)) { return 0; } break; case OPS_PKA_ELGAMAL: return __ops_write_mpi(output, seckey->key.elgamal.x); default: (void) fprintf(stderr, "Bad seckey->pubkey.alg\n"); return 0; } /* close rather than pop, since its the only one on the stack */ __ops_writer_close(output); __ops_teardown_memory_write(output, mem); /* should now have checksum in seckey struct */ /* test */ if (__ops_get_debug_level(__FILE__)) { test_seckey(seckey); } return 1; }