@ -231,7 +231,7 @@ pubkey_length(const pgp_pubkey_t *key)
static unsigned
seckey_length ( const pgp_seckey_t * key )
{
int len ;
int len = 0 ;
switch ( key - > pubkey . alg ) {
case PGP_PKA_EDDSA :
@ -239,22 +239,31 @@ seckey_length(const pgp_seckey_t *key)
/ / TODO
printf ( " %s:%d, %s: Elliptic curves pub(%d) \n " , __FILE__ , __LINE__ , __FUNCTION__ , key - > pubkey . alg ) ;
break ;
case PGP_PKA_DSA :
return ( unsign ed ) ( mpi_length ( key - > key . dsa . x ) + pubkey_length ( & key - > pubkey ) ) ;
case PGP_PKA_RSA :
len = mpi_length ( key - > key . rsa . d ) + mpi_length ( key - > key . rsa . p ) +
mpi_length ( key - > key . rsa . q ) + mpi_length ( key - > key . rsa . u ) ;
l en =
mpi_length ( key - > key . dsa . x )
+ pubkey_length ( & key - > pubkey ) ;
break ;
return ( unsigned ) ( len + pubkey_length ( & key - > pubkey ) ) ;
case PGP_PKA_RSA :
len =
mpi_length ( key - > key . rsa . d )
+ mpi_length ( key - > key . rsa . p )
+ mpi_length ( key - > key . rsa . q )
+ mpi_length ( key - > key . rsa . u )
+ pubkey_length ( & key - > pubkey ) ;
break ;
case PGP_PKA_ELGAMAL :
return ( unsigned ) (
mpi_length ( key - > key . dsa . x ) + pubkey_length ( & key - > pubkey ) ) ;
len =
mpi_length ( key - > key . dsa . x )
+ pubkey_length ( & key - > pubkey ) ;
default :
( void ) fprintf ( stderr , " seckey_length: unknown key algorithm \n " ) ;
}
return 0 ;
return len ;
}
# ifdef HAVE_OPENSSL
@ -332,17 +341,15 @@ write_pubkey_body(const pgp_pubkey_t *key, pgp_output_t *output)
* verification .
*/
static unsigned
write_seckey_body ( const pgp_seckey_t * key ,
const uint8_t * passphrase ,
const size_t pplen ,
pgp_output_t * output )
write_seckey_body ( const pgp_seckey_t * key , pgp_output_t * output )
{
/* RFC4880 Section 5.5.3 Secret-Key Packet Formats */
pgp_crypt_t crypted ;
pgp_hash_t hash ;
pgp_hash_t hash ;
unsigned done = 0 ;
unsigned i = 0 ;
uint8_t sesskey [ CAST_KEY_LENGTH ] ;
memset ( & hash , 0 , sizeof ( pgp_hash_t ) ) ;
if ( ! write_pubkey_body ( & key - > pubkey , output ) ) {
return 0 ;
@ -355,17 +362,15 @@ write_seckey_body(const pgp_seckey_t *key,
( void ) fprintf ( stderr , " write_seckey_body: s2k usage \n " ) ;
return 0 ;
}
if ( key - > alg ! = PGP_SA_CAST5 ) {
( void ) fprintf ( stderr , " write_seckey_body: algorithm \n " ) ;
return 0 ;
}
if ( ! pgp_write_scalar ( output , ( unsigned ) key - > alg , 1 ) ) {
return 0 ;
}
if ( key - > s2k_specifier ! = PGP_S2KS_SIMPLE & &
key - > s2k_specifier ! = PGP_S2KS_SALTED ) {
if (
key - > s2k_specifier ! = PGP_S2KS_SIMPLE & &
key - > s2k_specifier ! = PGP_S2KS_ITERATED_AND_SALTED & &
key - > s2k_specifier ! = PGP_S2KS_SALTED
) {
/* = 1 \todo could also be iterated-and-salted */
( void ) fprintf ( stderr , " write_seckey_body: s2k spec \n " ) ;
return 0 ;
@ -382,6 +387,12 @@ write_seckey_body(const pgp_seckey_t *key,
/* nothing more to do */
break ;
/*
* \ todo case PGP_S2KS_ITERATED_AND_SALTED : / / 8 - octet salt
* value / / 1 - octet count break ;
*/
case PGP_S2KS_ITERATED_AND_SALTED :
case PGP_S2KS_SALTED :
/* 8-octet salt value */
pgp_random ( __UNCONST ( & key - > salt [ 0 ] ) , PGP_SALT_SIZE ) ;
@ -390,15 +401,8 @@ write_seckey_body(const pgp_seckey_t *key,
}
break ;
/*
* \ todo case PGP_S2KS_ITERATED_AND_SALTED : / / 8 - octet salt
* value / / 1 - octet count break ;
*/
default :
( void ) fprintf ( stderr ,
" invalid/unsupported s2k specifier %d \n " ,
key - > s2k_specifier ) ;
( void ) fprintf ( stderr , " invalid/unsupported s2k specifier %d \n " , key - > s2k_specifier ) ;
return 0 ;
}
@ -414,9 +418,10 @@ write_seckey_body(const pgp_seckey_t *key,
switch ( key - > s2k_specifier ) {
case PGP_S2KS_SIMPLE :
case PGP_S2KS_SALTED :
/* RFC4880: section 3.7.1.1 and 3.7.1.2 */
case PGP_S2KS_ITERATED_AND_SALTED :
/* RFC4880: section 3.7.1.1 and 3.7.1.2 and 3.7.1.3 */
for ( done = 0 , i = 0 ; done < CAST_KEY_LENGTH ; i + + ) {
for ( done = 0 , i = 0 ; done < pgp_key_size ( key - > alg ) ; i + + ) {
unsigned hashsize ;
unsigned j ;
unsigned needed ;
@ -424,10 +429,9 @@ write_seckey_body(const pgp_seckey_t *key,
uint8_t zero = 0 ;
uint8_t * hashed ;
/* Hard-coded SHA1 for session key */
pgp_hash_any ( & hash , PGP_HASH_SHA1 ) ;
pgp_hash_any ( & hash , key - > hash_alg ) ;
hashsize = pgp_hash_size ( key - > hash_alg ) ;
needed = CAST_KEY_LENGTH - done ;
needed = pgp_key_size ( key - > alg ) - done ;
size = MIN ( needed , hashsize ) ;
if ( ( hashed = calloc ( 1 , hashsize ) ) = = NULL ) {
( void ) fprintf ( stderr , " write_seckey_body: bad alloc \n " ) ;
@ -454,7 +458,7 @@ write_seckey_body(const pgp_seckey_t *key,
if ( key - > s2k_specifier = = PGP_S2KS_SALTED ) {
hash . add ( & hash , key - > salt , PGP_SALT_SIZE ) ;
}
hash . add ( & hash , passphrase , ( unsigned ) pplen ) ;
hash . add ( & hash , key - > passphrase , strlen ( key - > passphrase ) ) ;
hash . finish ( & hash , hashed ) ;
/*
@ -465,19 +469,15 @@ write_seckey_body(const pgp_seckey_t *key,
hashed , ( unsigned ) size ) ;
done + = ( unsigned ) size ;
free ( hashed ) ;
if ( done > CAST_KEY_LENGTH ) {
( void ) fprintf ( stderr ,
" write_seckey_body: short add \n " ) ;
if ( done > pgp_key_size ( key - > alg ) ) {
( void ) fprintf ( stderr , " write_seckey_body: short add \n " ) ;
return 0 ;
}
}
break ;
/ / if ( key - > s2k_specifier = = PGP_S2KS_ITERATED_AND_SALTED )
/*
* \ todo case PGP_S2KS_ITERATED_AND_SALTED : * 8 - octet salt
* value * 1 - octet count break ;
*/
break ;
default :
( void ) fprintf ( stderr ,
@ -495,7 +495,7 @@ write_seckey_body(const pgp_seckey_t *key,
if ( pgp_get_debug_level ( __FILE__ ) ) {
hexdump ( stderr , " writing: iv= " , key - > iv , pgp_block_size ( key - > alg ) ) ;
hexdump ( stderr , " key= " , sesskey , CAST_KEY_LENGTH ) ;
hexdump ( stderr , " key= " , sesskey , pgp_key_size ( key - > alg ) ) ;
( void ) fprintf ( stderr , " \n turning encryption on... \n " ) ;
}
pgp_push_enc_crypt ( output , & crypted ) ;
@ -571,6 +571,108 @@ pgp_write_struct_pubkey(pgp_output_t *output, const pgp_pubkey_t *key)
return pgp_write_struct_pubkey_ptag ( output , key , PGP_PTAG_CT_PUBLIC_KEY ) ;
}
/**
* \ ingroup Core_WritePackets
* \ brief Writes a Secret Key packet .
* \ param key The secret key
* \ param passphrase The passphrase
* \ param pplen Length of passphrase
* \ param output
* \ return 1 if OK ; else 0
*/
unsigned
pgp_write_struct_crypted_seckey_ptag ( const pgp_seckey_t * key , pgp_output_t * output , pgp_content_enum ptag )
{
int length = 0 ;
if ( key - > pubkey . version ! = 4 ) {
( void ) fprintf ( stderr , " pgp_write_struct_seckey: public key version \n " ) ;
return 0 ;
}
/* Ref: RFC4880 Section 5.5.3 */
/* pubkey, excluding MPIs */
length + = 1 + 4 + 1 ;
/* s2k usage */
length + = 1 ;
switch ( key - > s2k_usage ) {
case PGP_S2KU_NONE :
/* nothing to add */
break ;
case PGP_S2KU_ENCRYPTED_AND_HASHED : /* 254 */
case PGP_S2KU_ENCRYPTED : /* 255 */
/* Ref: RFC4880 Section 3.7 */
length + = 1 ; /* s2k_specifier */
switch ( key - > s2k_specifier ) {
case PGP_S2KS_SIMPLE :
length + = 1 ; /* hash algorithm */
break ;
case PGP_S2KS_SALTED :
length + = 1 + 8 ; /* hash algorithm + salt */
break ;
case PGP_S2KS_ITERATED_AND_SALTED :
length + = 1 + 8 + 1 ; /* hash algorithm, salt +
* count */
break ;
default :
( void ) fprintf ( stderr ,
" pgp_write_struct_seckey: s2k spec \n " ) ;
return 0 ;
}
break ;
default :
( void ) fprintf ( stderr ,
" pgp_write_struct_seckey: s2k usage \n " ) ;
return 0 ;
}
/* IV */
if ( key - > s2k_usage ) {
length + = pgp_block_size ( key - > alg ) ;
}
/* checksum or hash */
switch ( key - > s2k_usage ) {
case PGP_S2KU_NONE :
case PGP_S2KU_ENCRYPTED :
length + = 2 ;
break ;
case PGP_S2KU_ENCRYPTED_AND_HASHED :
length + = PGP_CHECKHASH_SIZE ;
break ;
default :
( void ) fprintf ( stderr ,
" pgp_write_struct_seckey: s2k cksum usage \n " ) ;
return 0 ;
}
/* secret key and public key MPIs */
/ / length + = ( unsigned ) seckey_length ( key ) ;
pgp_write_ptag ( output , ptag ) ;
if ( ! write_pubkey_body ( & key - > pubkey , output ) ) {
return 0 ;
}
/ / & &
/* pgp_write_length(output,1+4+1+1+seckey_length(key)+2) && */
/ / pgp_write_length ( output , ( unsigned ) length ) & &
/ / write_seckey_body ( key , output ) ;
return 1 ;
}
/**
\ ingroup HighLevel_KeyWrite
@ -597,6 +699,7 @@ pgp_write_xfer_key(pgp_output_t *output,
unsigned subkeyidx = 0 ;
unsigned subkeysigidx = 0 ;
pgp_subkeysig_t * subkeysigp ;
int i ;
if ( armoured ) {
pgp_writer_push_armoured ( output , ( key - > type = = PGP_PTAG_CT_PUBLIC_KEY ) ? PGP_PGP_PUBLIC_KEY_BLOCK : PGP_PGP_PRIVATE_KEY_BLOCK ) ;
@ -607,8 +710,12 @@ pgp_write_xfer_key(pgp_output_t *output,
if ( ! pgp_write_struct_pubkey ( output , & key - > key . pubkey ) ) {
return 0 ;
}
} else {
if ( ! pgp_write_struct_seckey ( & key - > key . seckey , ( const uint8_t * ) " " , 0 , output ) ) {
} else {
if ( key - > key . seckey . encrypted ) {
if ( ! pgp_write_struct_crypted_seckey_ptag ( & key - > key . seckey , output , PGP_PTAG_CT_SECRET_KEY ) ) {
return 0 ;
}
} else if ( ! pgp_write_struct_seckey ( & key - > key . seckey , output ) ) {
return 0 ;
}
}
@ -647,27 +754,27 @@ pgp_write_xfer_key(pgp_output_t *output,
/* Loop over key's subkeys */
subkeyp = key - > subkeys ;
printf ( " Having %d subkeys \n " , key - > subkeyc ) ;
for ( subkeyidx = 0 ; subkeyidx < key - > subkeyc ; subkeyidx + + , subkeyp + + )
{
if ( key - > type = = PGP_PTAG_CT_PUBLIC_KEY ) {
if ( ! pgp_write_struct_pubkey_ptag (
output , & subkeyp - > key . pubkey ,
PGP_PTAG_CT_PUBLIC_SUBKEY ) ) {
if ( ! pgp_write_struct_pubkey_ptag ( output , & subkeyp - > key . pubkey , PGP_PTAG_CT_PUBLIC_SUBKEY ) ) {
return 0 ;
}
} else {
if ( ! pgp_write_struct_seckey_ptag (
/* TODO support passphrase again */
& subkeyp - > key . seckey , ( const uint8_t * ) " " , 0 , output ,
PGP_PTAG_CT_SECRET_SUBKEY ) ) {
} else {
if ( key - > key . seckey . encrypted ) {
if ( ! pgp_write_struct_crypted_seckey_ptag ( & subkeyp - > key . seckey , output , PGP_PTAG_CT_SECRET_SUBKEY ) ) {
return 0 ;
}
} else
if ( ! pgp_write_struct_seckey_ptag ( & subkeyp - > key . seckey , output , PGP_PTAG_CT_SECRET_SUBKEY ) ) {
return 0 ;
}
}
/* Loop over key's subkeys sigs */
subkeysigp = key - > subkeysigs ;
for ( subkeysigidx = 0 ; subkeysigidx < key - > subkeysigc ;
subkeysigidx + + , subkeysigp + + )
for ( subkeysigidx = 0 ; subkeysigidx < key - > subkeysigc ; subkeysigidx + + , subkeysigp + + )
{
/* matching selected subkey */
if ( subkeysigp - > subkey = = subkeyidx )
@ -780,17 +887,12 @@ pgp_build_pubkey(pgp_memory_t *out, const pgp_pubkey_t *key, unsigned make_packe
* \ return 1 if OK ; else 0
*/
unsigned
pgp_write_struct_seckey_ptag ( const pgp_seckey_t * key ,
const uint8_t * passphrase ,
const size_t pplen ,
pgp_output_t * output ,
pgp_content_enum ptag )
pgp_write_struct_seckey_ptag ( const pgp_seckey_t * key , pgp_output_t * output , pgp_content_enum ptag )
{
int length = 0 ;
int length = 0 ;
if ( key - > pubkey . version ! = 4 ) {
( void ) fprintf ( stderr ,
" pgp_write_struct_seckey: public key version \n " ) ;
( void ) fprintf ( stderr , " pgp_write_struct_seckey: public key version \n " ) ;
return 0 ;
}
@ -844,6 +946,7 @@ pgp_write_struct_seckey_ptag(const pgp_seckey_t *key,
if ( key - > s2k_usage ) {
length + = pgp_block_size ( key - > alg ) ;
}
/* checksum or hash */
switch ( key - > s2k_usage ) {
case PGP_S2KU_NONE :
@ -863,21 +966,16 @@ pgp_write_struct_seckey_ptag(const pgp_seckey_t *key,
/* secret key and public key MPIs */
length + = ( unsigned ) seckey_length ( key ) ;
return pgp_write_ptag ( output , ptag ) & &
/* pgp_write_length(output,1+4+1+1+seckey_length(key)+2) && */
pgp_write_length ( output , ( unsigned ) length ) & &
write_seckey_body ( key , passphrase , pplen , output ) ;
write_seckey_body ( key , output ) ;
}
unsigned
pgp_write_struct_seckey ( const pgp_seckey_t * key ,
const uint8_t * passphrase ,
const size_t pplen ,
pgp_output_t * output )
pgp_write_struct_seckey ( const pgp_seckey_t * key , pgp_output_t * output )
{
return pgp_write_struct_seckey_ptag (
key , passphrase , pplen , output , PGP_PTAG_CT_SECRET_KEY ) ;
return pgp_write_struct_seckey_ptag ( key , output , PGP_PTAG_CT_SECRET_KEY ) ;
}
/**
* \ ingroup Core_Create
@ -1098,21 +1196,18 @@ pgp_create_pk_sesskey(pgp_key_t *key, const char *ciphername, pgp_pk_sesskey_t *
break ;
}
if ( ( encoded_m_buf = calloc ( 1 , sz_encoded_m_buf ) ) = = NULL ) {
( void ) fprintf ( stderr ,
" pgp_create_pk_sesskey: can't allocate \n " ) ;
( 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 " ) ;
( 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 " ) ;
( void ) fprintf ( stderr , " pgp_create_pk_sesskey: bad type (%d) \n " , key - > type ) ;
free ( unencoded_m_buf ) ;
free ( encoded_m_buf ) ;
free ( sesskey ) ;
@ -1136,8 +1231,7 @@ pgp_create_pk_sesskey(pgp_key_t *key, const char *ciphername, pgp_pk_sesskey_t *
case PGP_PKA_ELGAMAL :
break ;
default :
( void ) fprintf ( stderr ,
" pgp_create_pk_sesskey: bad pubkey algorithm \n " ) ;
( void ) fprintf ( stderr , " pgp_create_pk_sesskey: bad pubkey algorithm \n " ) ;
free ( unencoded_m_buf ) ;
free ( encoded_m_buf ) ;
free ( sesskey ) ;