/** \ingroup Core_Create \brief Creates an pgp_pk_sesskey_t struct from keydata \param key Keydata to use \return pgp_pk_sesskey_t struct \note It is the caller's responsiblity to free the returned pointer \note Currently hard-coded to use CAST5 \note Currently hard-coded to use RSA */ pgp_pk_sesskey_t * pgp_create_pk_sesskey(const pgp_key_t *key, const char *ciphername) { /* * Creates a random session key and encrypts it for the given key * * Encryption used is PK, * can be any, we're hardcoding RSA for now */ const pgp_pubkey_t *pubkey; pgp_pk_sesskey_t *sesskey; pgp_symm_alg_t cipher; const uint8_t *id; pgp_crypt_t cipherinfo; uint8_t *unencoded_m_buf; uint8_t *encoded_m_buf; size_t sz_encoded_m_buf; if (memcmp(key->encid, "\0\0\0\0\0\0\0\0", 8) == 0) { pubkey = pgp_get_pubkey(key); id = key->sigid; } else { pubkey = &key->enckey; id = key->encid; } /* allocate unencoded_m_buf here */ (void) memset(&cipherinfo, 0x0, sizeof(cipherinfo)); pgp_crypt_any(&cipherinfo, cipher = pgp_str_to_cipher((ciphername) ? ciphername : "cast5")); unencoded_m_buf = calloc(1, cipherinfo.keysize + 1 + 2); if (unencoded_m_buf == NULL) { (void) fprintf(stderr, "pgp_create_pk_sesskey: can't allocate\n"); return NULL; } switch(pubkey->alg) { case PGP_PKA_RSA: sz_encoded_m_buf = BN_num_bytes(pubkey->key.rsa.n); break; case PGP_PKA_DSA: case PGP_PKA_ELGAMAL: sz_encoded_m_buf = BN_num_bytes(pubkey->key.elgamal.p); break; default: sz_encoded_m_buf = 0; break; } if ((encoded_m_buf = calloc(1, sz_encoded_m_buf)) == NULL) { (void) fprintf(stderr, "pgp_create_pk_sesskey: can't allocate\n"); free(unencoded_m_buf); return NULL; } if ((sesskey = calloc(1, sizeof(*sesskey))) == NULL) { (void) fprintf(stderr, "pgp_create_pk_sesskey: can't allocate\n"); free(unencoded_m_buf); free(encoded_m_buf); return NULL; } if (key->type != PGP_PTAG_CT_PUBLIC_KEY) { (void) fprintf(stderr, "pgp_create_pk_sesskey: bad type\n"); free(unencoded_m_buf); free(encoded_m_buf); free(sesskey); return NULL; } sesskey->version = PGP_PKSK_V3; (void) memcpy(sesskey->key_id, id, sizeof(sesskey->key_id)); if (pgp_get_debug_level(__FILE__)) { hexdump(stderr, "Encrypting for keyid", id, sizeof(sesskey->key_id)); } switch (pubkey->alg) { case PGP_PKA_RSA: case PGP_PKA_DSA: case PGP_PKA_ELGAMAL: break; default: (void) fprintf(stderr, "pgp_create_pk_sesskey: bad pubkey algorithm\n"); free(unencoded_m_buf); free(encoded_m_buf); free(sesskey); return NULL; } sesskey->alg = pubkey->alg; sesskey->symm_alg = cipher; pgp_random(sesskey->key, cipherinfo.keysize); if (pgp_get_debug_level(__FILE__)) { hexdump(stderr, "sesskey created", sesskey->key, cipherinfo.keysize + 1 + 2); } if (create_unencoded_m_buf(sesskey, &cipherinfo, &unencoded_m_buf[0]) == 0) { free(unencoded_m_buf); free(encoded_m_buf); free(sesskey); return NULL; } if (pgp_get_debug_level(__FILE__)) { hexdump(stderr, "uuencoded m buf", unencoded_m_buf, cipherinfo.keysize + 1 + 2); } encode_m_buf(unencoded_m_buf, cipherinfo.keysize + 1 + 2, pubkey, encoded_m_buf); /* and encrypt it */ switch (key->key.pubkey.alg) { case PGP_PKA_RSA: if (!pgp_rsa_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pubkey, &sesskey->params)) { free(unencoded_m_buf); free(encoded_m_buf); free(sesskey); return NULL; } break; case PGP_PKA_DSA: case PGP_PKA_ELGAMAL: if (!pgp_elgamal_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pubkey, &sesskey->params)) { free(unencoded_m_buf); free(encoded_m_buf); free(sesskey); return NULL; } break; default: /* will not get here - for lint only */ break; } free(unencoded_m_buf); free(encoded_m_buf); return sesskey; }
/** \ingroup Core_Create \brief Creates an ops_pk_session_key_t struct from keydata \param key Keydata to use \return ops_pk_session_key_t struct \note It is the caller's responsiblity to free the returned pointer. Before freeing, the key must be cleared by calling ops_pk_session_key_free() \note Currently hard-coded to use CAST5 \note Currently hard-coded to use RSA */ ops_pk_session_key_t *ops_create_pk_session_key(const ops_keydata_t *key) { /* * Creates a random session key and encrypts it for the given key * * Session Key is for use with a SK algo, * can be any, we're hardcoding CAST5 for now * * Encryption used is PK, * can be any, we're hardcoding RSA for now */ const ops_public_key_t* pub_key=ops_get_public_key_from_data(key); #define SZ_UNENCODED_M_BUF CAST_KEY_LENGTH+1+2 unsigned char unencoded_m_buf[SZ_UNENCODED_M_BUF]; const size_t sz_encoded_m_buf=BN_num_bytes(pub_key->key.rsa.n); unsigned char* encoded_m_buf = ops_mallocz(sz_encoded_m_buf); ops_pk_session_key_t *session_key=ops_mallocz(sizeof *session_key); assert(key->type == OPS_PTAG_CT_PUBLIC_KEY); session_key->version=OPS_PKSK_V3; memcpy(session_key->key_id, key->key_id, sizeof session_key->key_id); if (debug) { unsigned int i=0; fprintf(stderr,"Encrypting for RSA key id : "); for (i=0; i<sizeof session_key->key_id; i++) fprintf(stderr,"%2x ", key->key_id[i]); fprintf(stderr,"\n"); } assert(key->key.pkey.algorithm == OPS_PKA_RSA); session_key->algorithm=key->key.pkey.algorithm; // \todo allow user to specify other algorithm session_key->symmetric_algorithm=OPS_SA_CAST5; ops_random(session_key->key, CAST_KEY_LENGTH); if (debug) { unsigned int i=0; fprintf(stderr,"CAST5 session key created (len=%d):\n ", CAST_KEY_LENGTH); for (i=0; i<CAST_KEY_LENGTH; i++) fprintf(stderr,"%2x ", session_key->key[i]); fprintf(stderr,"\n"); } if (create_unencoded_m_buf(session_key, &unencoded_m_buf[0])==ops_false) { free(encoded_m_buf); return NULL; } if (debug) { unsigned int i=0; printf("unencoded m buf:\n"); for (i=0; i<SZ_UNENCODED_M_BUF; i++) printf("%2x ", unencoded_m_buf[i]); printf("\n"); } encode_m_buf(&unencoded_m_buf[0], SZ_UNENCODED_M_BUF, pub_key, &encoded_m_buf[0]); // and encrypt it if(!ops_rsa_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pub_key, &session_key->parameters)) { free (encoded_m_buf); return NULL; } free(encoded_m_buf); return session_key; }