mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
fingerprints and self signatures added
This commit is contained in:
parent
3b1b6f9d98
commit
935965049d
8
TODO
8
TODO
@ -4,15 +4,13 @@
|
||||
this shoud espceially done for the buffer in the chain.
|
||||
* add a way to difference between errors and eof in the underflow/flush
|
||||
function of iobuf.
|
||||
* filter all output read from the input when displaying it to the user.
|
||||
* check that all output is filtered when displayed.
|
||||
* keyring editing
|
||||
* add trust stuff
|
||||
* make ttyio.c work (hide passwords etc..)
|
||||
* add detached signatures
|
||||
* add option file handling.
|
||||
* use correct ASN values for DEK encoding
|
||||
* add checking of armor trailers
|
||||
* fix the memory stuff (secure memory)
|
||||
* add real secure memory
|
||||
* look for a way to reuse RSA signatures
|
||||
* find a way to remove the armor filter after it
|
||||
@ -24,10 +22,12 @@
|
||||
* enable a SIGSEGV handler while using zlib functions
|
||||
|
||||
* PGP writes the signature and then the file, this is not
|
||||
a good idea, we can't write such files if we take input rom stdin.
|
||||
a good idea, we can't write such files if we take input from stdin.
|
||||
So the solution will: accept such packet, but write
|
||||
signature the corret way: first the data and then the signature[s]
|
||||
this is much easier to check, also we must read the entire data
|
||||
before we can check wether we have the pubkey or not. The one-pass
|
||||
signature packets should be implemented to avoid this.
|
||||
|
||||
* compress does not work always!
|
||||
|
||||
|
@ -95,7 +95,7 @@ gen_k( MPI p )
|
||||
if( DBG_CIPHER )
|
||||
fputc('.', stderr);
|
||||
mpi_set_bytes( k, nbits, get_random_byte, 1 );
|
||||
mpi_set_bit( k, nbits-1 ); /* make sure it's high (needed?) */
|
||||
mpi_set_bit( k, nbits-1 ); /* make sure it's high (really needed?) */
|
||||
if( mpi_cmp( k, p_1 ) >= 0 )
|
||||
continue; /* is not smaller than (p-1) */
|
||||
if( mpi_gcd( temp, k, p_1 ) )
|
||||
@ -136,7 +136,7 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk, unsigned nbits )
|
||||
fputc('.', stderr);
|
||||
mpi_set_bytes( x, nbits, get_random_byte, 1 ); /* fixme: should be 2 */
|
||||
mpi_set_bit( x, nbits-1 ); /* make sure it's high (needed?) */
|
||||
} while( mpi_cmp( x, p ) >= 0 ); /* x must be samller than p */
|
||||
} while( mpi_cmp( x, p ) >= 0 ); /* x must be smaller than p */
|
||||
|
||||
y = mpi_alloc(nbits/BITS_PER_MPI_LIMB);
|
||||
mpi_powm( y, g, x, p );
|
||||
|
@ -98,8 +98,7 @@ gen_prime( unsigned nbits, int secret )
|
||||
}
|
||||
if( x )
|
||||
continue; /* found a multiple of a already known prime */
|
||||
if( DBG_CIPHER )
|
||||
fputc('.', stderr);
|
||||
fputc('.', stderr);
|
||||
|
||||
mpi_add_ui( prime, prime, step );
|
||||
|
||||
@ -108,8 +107,7 @@ gen_prime( unsigned nbits, int secret )
|
||||
mpi_powm( result, val_2, prime, prime );
|
||||
if( mpi_cmp_ui(result, 2) )
|
||||
continue; /* stepping (fermat test failed) */
|
||||
if( DBG_CIPHER )
|
||||
fputc('+', stderr);
|
||||
fputc('+', stderr);
|
||||
|
||||
/* perform stronger tests */
|
||||
if( !is_not_prime(prime, nbits, 5, &count2 ) ) {
|
||||
@ -120,8 +118,9 @@ gen_prime( unsigned nbits, int secret )
|
||||
break; /* step loop, cont with a new prime */
|
||||
}
|
||||
}
|
||||
|
||||
fputc('\n', stderr);
|
||||
if( DBG_CIPHER ) {
|
||||
fputc('\n', stderr);
|
||||
log_debug("performed %u simple and %u stronger tests\n",
|
||||
count1, count2 );
|
||||
log_mpidump("found prime: ", prime );
|
||||
@ -134,8 +133,7 @@ gen_prime( unsigned nbits, int secret )
|
||||
return prime;
|
||||
}
|
||||
}
|
||||
if( DBG_CIPHER )
|
||||
fputc(':', stderr); /* restart with a new random value */
|
||||
fputc(':', stderr); /* restart with a new random value */
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,8 +177,7 @@ is_not_prime( MPI n, unsigned nbits, int steps, int *count )
|
||||
if( j == k )
|
||||
goto leave;
|
||||
}
|
||||
if( DBG_CIPHER )
|
||||
fputc('+', stderr);
|
||||
fputc('+', stderr);
|
||||
}
|
||||
rc = 0; /* may be a prime */
|
||||
|
||||
|
16
cipher/rsa.c
16
cipher/rsa.c
@ -157,6 +157,22 @@ rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits )
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Test wether the secret key is valid.
|
||||
* Returns: true if this is a valid key.
|
||||
*/
|
||||
int
|
||||
rsa_check_secret_key( RSA_secret_key *sk )
|
||||
{
|
||||
int rc;
|
||||
MPI temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 );
|
||||
|
||||
mpi_mul(temp, sk->p, sk->q );
|
||||
rc = mpi_cmp( temp, sk->n );
|
||||
mpi_free(temp);
|
||||
return !rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
|
@ -46,6 +46,7 @@ typedef struct {
|
||||
void rsa_free_public_key( RSA_public_key *pk );
|
||||
void rsa_free_secret_key( RSA_secret_key *sk );
|
||||
void rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits );
|
||||
int rsa_check_secret_key( RSA_secret_key *sk );
|
||||
void rsa_public(MPI output, MPI input, RSA_public_key *skey );
|
||||
void rsa_secret(MPI output, MPI input, RSA_secret_key *skey );
|
||||
|
||||
|
@ -169,13 +169,13 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc )
|
||||
write_16(a, pkc->valid_days );
|
||||
iobuf_put(a, pkc->pubkey_algo );
|
||||
if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||
mpi_encode(a, pkc->d.elg.p );
|
||||
mpi_encode(a, pkc->d.elg.g );
|
||||
mpi_encode(a, pkc->d.elg.y );
|
||||
mpi_write(a, pkc->d.elg.p );
|
||||
mpi_write(a, pkc->d.elg.g );
|
||||
mpi_write(a, pkc->d.elg.y );
|
||||
}
|
||||
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
mpi_encode(a, pkc->d.rsa.rsa_n );
|
||||
mpi_encode(a, pkc->d.rsa.rsa_e );
|
||||
mpi_write(a, pkc->d.rsa.rsa_n );
|
||||
mpi_write(a, pkc->d.rsa.rsa_e );
|
||||
}
|
||||
else {
|
||||
rc = G10ERR_PUBKEY_ALGO;
|
||||
@ -191,6 +191,31 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc )
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Make a hash value from the public key certificate
|
||||
*/
|
||||
void
|
||||
hash_public_cert( MD_HANDLE *md, PKT_public_cert *pkc )
|
||||
{
|
||||
PACKET pkt;
|
||||
int rc = 0;
|
||||
int c;
|
||||
IOBUF a = iobuf_temp();
|
||||
|
||||
/* build the packet */
|
||||
init_packet(&pkt);
|
||||
pkt.pkttype = PKT_PUBLIC_CERT;
|
||||
pkt.pkt.public_cert = pkc;
|
||||
if( (rc = build_packet( a, &pkt )) )
|
||||
log_fatal("build public_cert for hashing failed: %s\n", g10_errstr(rc));
|
||||
while( (c=iobuf_get(a)) != -1 )
|
||||
md_putchar( md, c );
|
||||
|
||||
iobuf_cancel(a);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
|
||||
{
|
||||
@ -202,48 +227,33 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
|
||||
write_16(a, skc->valid_days );
|
||||
iobuf_put(a, skc->pubkey_algo );
|
||||
if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||
mpi_encode(a, skc->d.elg.p );
|
||||
mpi_encode(a, skc->d.elg.g );
|
||||
mpi_encode(a, skc->d.elg.y );
|
||||
mpi_write(a, skc->d.elg.p );
|
||||
mpi_write(a, skc->d.elg.g );
|
||||
mpi_write(a, skc->d.elg.y );
|
||||
iobuf_put(a, skc->d.elg.protect_algo );
|
||||
skc->d.elg.calc_csum = 0;
|
||||
if( skc->d.elg.protect_algo ) {
|
||||
assert( skc->d.elg.is_protected == 1 );
|
||||
assert( skc->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH );
|
||||
iobuf_write(a, skc->d.elg.protect.blowfish.iv, 8 );
|
||||
mpi_write_csum(a, (byte*)skc->d.elg.x, &skc->d.elg.calc_csum );
|
||||
}
|
||||
else { /* not protected */
|
||||
assert( !skc->d.elg.is_protected );
|
||||
mpi_encode_csum(a, skc->d.elg.x, &skc->d.elg.calc_csum );
|
||||
}
|
||||
|
||||
write_16(a, skc->d.elg.calc_csum );
|
||||
mpi_write(a, skc->d.elg.x );
|
||||
write_16(a, skc->d.elg.csum );
|
||||
}
|
||||
else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
mpi_encode(a, skc->d.rsa.rsa_n );
|
||||
mpi_encode(a, skc->d.rsa.rsa_e );
|
||||
mpi_write(a, skc->d.rsa.rsa_n );
|
||||
mpi_write(a, skc->d.rsa.rsa_e );
|
||||
iobuf_put(a, skc->d.rsa.protect_algo );
|
||||
skc->d.rsa.calc_csum = 0;
|
||||
if( skc->d.rsa.protect_algo ) {
|
||||
assert( skc->d.rsa.is_protected == 1 );
|
||||
assert( skc->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH );
|
||||
iobuf_write(a, skc->d.rsa.protect.blowfish.iv, 8 );
|
||||
|
||||
mpi_write_csum(a, (byte*)skc->d.rsa.rsa_d, &skc->d.rsa.calc_csum );
|
||||
mpi_write_csum(a, (byte*)skc->d.rsa.rsa_p, &skc->d.rsa.calc_csum );
|
||||
mpi_write_csum(a, (byte*)skc->d.rsa.rsa_q, &skc->d.rsa.calc_csum );
|
||||
mpi_write_csum(a, (byte*)skc->d.rsa.rsa_u, &skc->d.rsa.calc_csum );
|
||||
}
|
||||
else { /* Not protected: You fool you! */
|
||||
assert( !skc->d.rsa.is_protected );
|
||||
mpi_encode_csum(a, skc->d.rsa.rsa_d, &skc->d.rsa.calc_csum );
|
||||
mpi_encode_csum(a, skc->d.rsa.rsa_p, &skc->d.rsa.calc_csum );
|
||||
mpi_encode_csum(a, skc->d.rsa.rsa_q, &skc->d.rsa.calc_csum );
|
||||
mpi_encode_csum(a, skc->d.rsa.rsa_u, &skc->d.rsa.calc_csum );
|
||||
}
|
||||
|
||||
write_16(a, skc->d.rsa.calc_csum );
|
||||
mpi_write(a, skc->d.rsa.rsa_d );
|
||||
mpi_write(a, skc->d.rsa.rsa_p );
|
||||
mpi_write(a, skc->d.rsa.rsa_q );
|
||||
mpi_write(a, skc->d.rsa.rsa_u );
|
||||
write_16(a, skc->d.rsa.csum );
|
||||
}
|
||||
else {
|
||||
rc = G10ERR_PUBKEY_ALGO;
|
||||
@ -270,11 +280,11 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
|
||||
write_32(a, enc->keyid[1] );
|
||||
iobuf_put(a,enc->pubkey_algo );
|
||||
if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||
mpi_encode(a, enc->d.elg.a );
|
||||
mpi_encode(a, enc->d.elg.b );
|
||||
mpi_write(a, enc->d.elg.a );
|
||||
mpi_write(a, enc->d.elg.b );
|
||||
}
|
||||
else if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
mpi_encode(a, enc->d.rsa.rsa_integer );
|
||||
mpi_write(a, enc->d.rsa.rsa_integer );
|
||||
}
|
||||
else {
|
||||
rc = G10ERR_PUBKEY_ALGO;
|
||||
@ -379,14 +389,14 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
|
||||
iobuf_put(a, sig->d.elg.digest_algo );
|
||||
iobuf_put(a, sig->d.elg.digest_start[0] );
|
||||
iobuf_put(a, sig->d.elg.digest_start[1] );
|
||||
mpi_encode(a, sig->d.elg.a );
|
||||
mpi_encode(a, sig->d.elg.b );
|
||||
mpi_write(a, sig->d.elg.a );
|
||||
mpi_write(a, sig->d.elg.b );
|
||||
}
|
||||
else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
iobuf_put(a, sig->d.rsa.digest_algo );
|
||||
iobuf_put(a, sig->d.rsa.digest_start[0] );
|
||||
iobuf_put(a, sig->d.rsa.digest_start[1] );
|
||||
mpi_encode(a, sig->d.rsa.rsa_integer );
|
||||
mpi_write(a, sig->d.rsa.rsa_integer );
|
||||
}
|
||||
else {
|
||||
rc = G10ERR_PUBKEY_ALGO;
|
||||
|
@ -100,26 +100,15 @@ free_secret_cert( PKT_secret_cert *cert )
|
||||
mpi_free( cert->d.elg.p );
|
||||
mpi_free( cert->d.elg.g );
|
||||
mpi_free( cert->d.elg.y );
|
||||
if( cert->d.rsa.is_protected )
|
||||
m_free( cert->d.elg.x );
|
||||
else
|
||||
mpi_free( cert->d.elg.x );
|
||||
mpi_free( cert->d.elg.x );
|
||||
}
|
||||
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
mpi_free( cert->d.rsa.rsa_n );
|
||||
mpi_free( cert->d.rsa.rsa_e );
|
||||
if( cert->d.rsa.is_protected ) {
|
||||
m_free( cert->d.rsa.rsa_d );
|
||||
m_free( cert->d.rsa.rsa_p );
|
||||
m_free( cert->d.rsa.rsa_q );
|
||||
m_free( cert->d.rsa.rsa_u );
|
||||
}
|
||||
else {
|
||||
mpi_free( cert->d.rsa.rsa_d );
|
||||
mpi_free( cert->d.rsa.rsa_p );
|
||||
mpi_free( cert->d.rsa.rsa_q );
|
||||
mpi_free( cert->d.rsa.rsa_u );
|
||||
}
|
||||
mpi_free( cert->d.rsa.rsa_d );
|
||||
mpi_free( cert->d.rsa.rsa_p );
|
||||
mpi_free( cert->d.rsa.rsa_q );
|
||||
mpi_free( cert->d.rsa.rsa_u );
|
||||
}
|
||||
m_free(cert);
|
||||
}
|
||||
|
14
g10/g10.c
14
g10/g10.c
@ -124,6 +124,8 @@ main( int argc, char **argv )
|
||||
{ 512, "cache-all" ,0, "hold everything in memory"},
|
||||
{ 513, "gen-prime" , 1, "\rgenerate a prime of length n" },
|
||||
{ 514, "test" , 0, "\rdevelopment usage" },
|
||||
{ 515, "change-passphrase", 0, "change the passphrase of your secret keyring"},
|
||||
{ 515, "fingerprint", 0, "show the fingerprints"},
|
||||
{0} };
|
||||
ARGPARSE_ARGS pargs = { &argc, &argv, 0 };
|
||||
IOBUF a;
|
||||
@ -136,11 +138,14 @@ main( int argc, char **argv )
|
||||
int nrings=0;
|
||||
armor_filter_context_t afx;
|
||||
const char *s;
|
||||
int detached_sig = 0;
|
||||
|
||||
opt.compress = -1; /* defaults to default compression level */
|
||||
while( arg_parse( &pargs, opts) ) {
|
||||
switch( pargs.r_opt ) {
|
||||
case 'v': opt.verbose++; break;
|
||||
case 'v': opt.verbose++;
|
||||
opt.list_sigs=1;
|
||||
break;
|
||||
case 'z':
|
||||
opt.compress = pargs.r.ret_int;
|
||||
break;
|
||||
@ -151,7 +156,7 @@ main( int argc, char **argv )
|
||||
opt.outfile_is_stdout = 1;
|
||||
break;
|
||||
case 'e': action = action == aSign? aSignEncr : aEncr; break;
|
||||
case 'b': opt.detached_sig = 1;
|
||||
case 'b': detached_sig = 1;
|
||||
/* fall trough */
|
||||
case 's': action = action == aEncr? aSignEncr : aSign; break;
|
||||
case 'l': /* store the local users */
|
||||
@ -171,13 +176,14 @@ main( int argc, char **argv )
|
||||
case 502: opt.answer_no = 1; break;
|
||||
case 503: action = aKeygen; break;
|
||||
case 507: action = aStore; break;
|
||||
case 508: opt.check_sigs = 1; break;
|
||||
case 508: opt.check_sigs = 1; opt.list_sigs = 1; break;
|
||||
case 509: add_keyring(pargs.r.ret_str); nrings++; break;
|
||||
case 510: opt.debug |= pargs.r.ret_ulong; break;
|
||||
case 511: opt.debug = ~0; break;
|
||||
case 512: opt.cache_all = 1; break;
|
||||
case 513: action = aPrimegen; break;
|
||||
case 514: action = aTest; break;
|
||||
case 515: opt.fingerprint = 1; break;
|
||||
default : pargs.err = 2; break;
|
||||
}
|
||||
}
|
||||
@ -230,7 +236,7 @@ main( int argc, char **argv )
|
||||
case aSign: /* sign the given file */
|
||||
if( argc > 1 )
|
||||
usage(1);
|
||||
if( (rc = sign_file(fname, opt.detached_sig, locusr)) )
|
||||
if( (rc = sign_file(fname, detached_sig, locusr)) )
|
||||
log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) );
|
||||
break;
|
||||
|
||||
|
@ -50,6 +50,8 @@ unsigned nbits_from_skc( PKT_secret_cert *skc );
|
||||
const char *datestr_from_pkc( PKT_public_cert *pkc );
|
||||
const char *datestr_from_skc( PKT_secret_cert *skc );
|
||||
const char *datestr_from_sig( PKT_signature *sig );
|
||||
byte *fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len );
|
||||
byte *fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len );
|
||||
|
||||
|
||||
|
||||
|
200
g10/keygen.c
200
g10/keygen.c
@ -51,9 +51,44 @@ answer_is_yes( const char *s )
|
||||
}
|
||||
|
||||
|
||||
static u16
|
||||
checksum_u16( unsigned n )
|
||||
{
|
||||
u16 a;
|
||||
|
||||
a = (n >> 8) & 0xff;
|
||||
a |= n & 0xff;
|
||||
return a;
|
||||
}
|
||||
|
||||
static u16
|
||||
checksum( byte *p, unsigned n )
|
||||
{
|
||||
u16 a;
|
||||
|
||||
for(a=0; n; n-- )
|
||||
a += *p++;
|
||||
return a;
|
||||
}
|
||||
|
||||
static u16
|
||||
checksum_mpi( MPI a )
|
||||
{
|
||||
u16 csum;
|
||||
byte *buffer;
|
||||
unsigned nbytes;
|
||||
|
||||
buffer = mpi_get_buffer( a, &nbytes, NULL );
|
||||
csum = checksum_u16( nbytes*8 );
|
||||
csum += checksum( buffer, nbytes );
|
||||
m_free( buffer );
|
||||
return csum;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
write_uid( IOBUF out, const char *s )
|
||||
write_uid( IOBUF out, const char *s, PKT_user_id **upkt )
|
||||
{
|
||||
PACKET pkt;
|
||||
size_t n = strlen(s);
|
||||
@ -65,13 +100,44 @@ write_uid( IOBUF out, const char *s )
|
||||
strcpy(pkt.pkt.user_id->name, s);
|
||||
if( (rc = build_packet( out, &pkt )) )
|
||||
log_error("build_packet(user_id) failed: %s\n", g10_errstr(rc) );
|
||||
if( upkt ) {
|
||||
*upkt = pkt.pkt.user_id;
|
||||
pkt.pkt.user_id = NULL;
|
||||
}
|
||||
free_packet( &pkt );
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
write_selfsig( IOBUF out, PKT_public_cert *pkc, PKT_user_id *uid,
|
||||
PKT_secret_cert *skc )
|
||||
{
|
||||
PACKET pkt;
|
||||
PKT_signature *sig;
|
||||
int rc=0;
|
||||
|
||||
if( opt.verbose )
|
||||
log_info("writing self signature\n");
|
||||
|
||||
rc = make_keysig_packet( &sig, pkc, uid, skc, 0x13, DIGEST_ALGO_RMD160 );
|
||||
if( rc ) {
|
||||
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
pkt.pkttype = PKT_SIGNATURE;
|
||||
pkt.pkt.signature = sig;
|
||||
if( (rc = build_packet( out, &pkt )) )
|
||||
log_error("build_packet(signature) failed: %s\n", g10_errstr(rc) );
|
||||
free_packet( &pkt );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_RSA_CIPHER
|
||||
static int
|
||||
gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
|
||||
gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io, DEK *dek,
|
||||
PKT_public_cert **ret_pkc, PKT_secret_cert **ret_skc )
|
||||
{
|
||||
int rc;
|
||||
PACKET pkt1, pkt2;
|
||||
@ -80,6 +146,9 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
|
||||
RSA_public_key pk;
|
||||
RSA_secret_key sk;
|
||||
|
||||
init_packet(&pkt1);
|
||||
init_packet(&pkt2);
|
||||
|
||||
rsa_generate( &pk, &sk, nbits );
|
||||
|
||||
skc = m_alloc( sizeof *skc );
|
||||
@ -96,15 +165,28 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
|
||||
skc->d.rsa.rsa_p = sk.p;
|
||||
skc->d.rsa.rsa_q = sk.q;
|
||||
skc->d.rsa.rsa_u = sk.u;
|
||||
skc->d.rsa.calc_csum = 0;
|
||||
skc->d.rsa.is_protected = 0; /* FIXME!!! */
|
||||
skc->d.rsa.protect_algo = 0; /* should be blowfish */
|
||||
/*memcpy(skc->d.rsa.protect.blowfish.iv,"12345678", 8);*/
|
||||
skc->d.rsa.csum = checksum_mpi( skc->d.rsa.rsa_d );
|
||||
skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_p );
|
||||
skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_q );
|
||||
skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_u );
|
||||
if( !dek ) {
|
||||
skc->d.rsa.is_protected = 0;
|
||||
skc->d.rsa.protect_algo = 0;
|
||||
}
|
||||
else {
|
||||
skc->d.rsa.is_protected = 1;
|
||||
skc->d.rsa.protect_algo = CIPHER_ALGO_BLOWFISH;
|
||||
randomize_buffer( skc->d.rsa.protect.blowfish.iv, 8, 1);
|
||||
skc->d.rsa.csum += checksum( skc->d.rsa.protect.blowfish.iv, 8 );
|
||||
rc = protect_secret_key( skc, dek );
|
||||
if( rc ) {
|
||||
log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
init_packet(&pkt1);
|
||||
pkt1.pkttype = PKT_PUBLIC_CERT;
|
||||
pkt1.pkt.public_cert = pkc;
|
||||
init_packet(&pkt2);
|
||||
pkt2.pkttype = PKT_SECRET_CERT;
|
||||
pkt2.pkt.secret_cert = skc;
|
||||
|
||||
@ -116,6 +198,10 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
|
||||
log_error("build secret_cert packet failed: %s\n", g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
*ret_pkc = pkt1.pkt.public_cert;
|
||||
pkt1.pkt.public_cert = NULL;
|
||||
*ret_skc = pkt1.pkt.secret_cert;
|
||||
pkt1.pkt.secret_cert = NULL;
|
||||
|
||||
leave:
|
||||
free_packet(&pkt1);
|
||||
@ -125,14 +211,19 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
|
||||
#endif /*HAVE_RSA_CIPHER*/
|
||||
|
||||
static int
|
||||
gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
|
||||
gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io, DEK *dek,
|
||||
PKT_public_cert **ret_pkc, PKT_secret_cert **ret_skc )
|
||||
{
|
||||
int rc;
|
||||
PACKET pkt1, pkt2;
|
||||
PKT_secret_cert *skc;
|
||||
PKT_secret_cert *skc, *unprotected_skc;
|
||||
PKT_public_cert *pkc;
|
||||
ELG_public_key pk;
|
||||
ELG_secret_key sk;
|
||||
unsigned nbytes;
|
||||
|
||||
init_packet(&pkt1);
|
||||
init_packet(&pkt2);
|
||||
|
||||
elg_generate( &pk, &sk, nbits );
|
||||
|
||||
@ -150,15 +241,25 @@ gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
|
||||
skc->d.elg.y = sk.y;
|
||||
skc->d.elg.x = sk.x;
|
||||
|
||||
skc->d.elg.calc_csum = 0;
|
||||
skc->d.elg.is_protected = 0; /* FIXME!!! */
|
||||
skc->d.elg.protect_algo = 0; /* should be blowfish */
|
||||
/*memcpy(skc->d.elg.protect.blowfish.iv,"12345678", 8);*/
|
||||
skc->d.elg.csum = checksum_mpi( skc->d.elg.x );
|
||||
unprotected_skc = copy_secret_cert( NULL, skc );
|
||||
if( !dek ) {
|
||||
skc->d.elg.is_protected = 0;
|
||||
skc->d.elg.protect_algo = 0;
|
||||
}
|
||||
else {
|
||||
skc->d.elg.is_protected = 0;
|
||||
skc->d.elg.protect_algo = CIPHER_ALGO_BLOWFISH;
|
||||
randomize_buffer(skc->d.elg.protect.blowfish.iv, 8, 1);
|
||||
rc = protect_secret_key( skc, dek );
|
||||
if( rc ) {
|
||||
log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
init_packet(&pkt1);
|
||||
pkt1.pkttype = PKT_PUBLIC_CERT;
|
||||
pkt1.pkt.public_cert = pkc;
|
||||
init_packet(&pkt2);
|
||||
pkt2.pkttype = PKT_SECRET_CERT;
|
||||
pkt2.pkt.secret_cert = skc;
|
||||
|
||||
@ -170,10 +271,17 @@ gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
|
||||
log_error("build secret_cert packet failed: %s\n", g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
*ret_pkc = pkt1.pkt.public_cert;
|
||||
pkt1.pkt.public_cert = NULL;
|
||||
*ret_skc = unprotected_skc;
|
||||
unprotected_skc = NULL;
|
||||
|
||||
|
||||
leave:
|
||||
free_packet(&pkt1);
|
||||
free_packet(&pkt2);
|
||||
if( unprotected_skc )
|
||||
free_secret_cert( unprotected_skc );
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -192,6 +300,10 @@ generate_keypair()
|
||||
char *uid = NULL;
|
||||
IOBUF pub_io = NULL;
|
||||
IOBUF sec_io = NULL;
|
||||
PKT_public_cert *pkc = NULL;
|
||||
PKT_secret_cert *skc = NULL;
|
||||
PKT_user_id *upkt = NULL;
|
||||
DEK *dek = NULL;
|
||||
int rc;
|
||||
int algo;
|
||||
const char *algo_name;
|
||||
@ -301,6 +413,28 @@ generate_keypair()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
tty_printf( "You need a Passphrase to protect your secret key.\n\n" );
|
||||
|
||||
dek = m_alloc_secure( sizeof *dek );
|
||||
dek->algo = CIPHER_ALGO_BLOWFISH;
|
||||
rc = make_dek_from_passphrase( dek , 2 );
|
||||
if( rc == -1 ) {
|
||||
m_free(dek); dek = NULL;
|
||||
tty_printf(
|
||||
"You don't what a passphrase - this is probably a *bad* idea!\n"
|
||||
"I will do it anyway. You can change your passphrase at anytime,\n"
|
||||
"using this program with the option \"--change-passphrase\"\n\n" );
|
||||
}
|
||||
else if( rc ) {
|
||||
m_free(dek); dek = NULL;
|
||||
m_free(uid);
|
||||
log_error("Error getting the passphrase: %s\n", g10_errstr(rc) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* now check wether we a are allowed to write the keyrings */
|
||||
if( !(rc=overwrite_filep( pub_fname )) ) {
|
||||
if( !(pub_io = iobuf_create( pub_fname )) )
|
||||
@ -334,23 +468,41 @@ generate_keypair()
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
write_comment( pub_io, "#public key created by G10 pre-release " VERSION );
|
||||
write_comment( sec_io, "#secret key created by G10 pre-release " VERSION );
|
||||
|
||||
if( algo == PUBKEY_ALGO_ELGAMAL )
|
||||
gen_elg(nbits, pub_io, sec_io);
|
||||
rc = gen_elg(nbits, pub_io, sec_io, dek, &pkc, &skc);
|
||||
#ifdef HAVE_RSA_CIPHER
|
||||
else if( algo == PUBKEY_ALGO_RSA )
|
||||
gen_rsa(nbits, pub_io, sec_io);
|
||||
rc = gen_rsa(nbits, pub_io, sec_io, dek, &pkc, &skc);
|
||||
#endif
|
||||
else
|
||||
log_bug(NULL);
|
||||
write_uid(pub_io, uid );
|
||||
write_uid(sec_io, uid );
|
||||
m_free(uid);
|
||||
if( !rc )
|
||||
write_uid(pub_io, uid, &upkt );
|
||||
if( !rc )
|
||||
write_uid(sec_io, uid, NULL );
|
||||
if( !rc )
|
||||
rc = write_selfsig(pub_io, pkc, upkt, skc );
|
||||
|
||||
iobuf_close(pub_io);
|
||||
iobuf_close(sec_io);
|
||||
if( rc ) {
|
||||
iobuf_cancel(pub_io);
|
||||
iobuf_cancel(sec_io);
|
||||
tty_printf("Key generation failed: %s\n", g10_errstr(rc) );
|
||||
}
|
||||
else {
|
||||
iobuf_close(pub_io);
|
||||
iobuf_close(sec_io);
|
||||
tty_printf("public and secret key created and signed.\n" );
|
||||
}
|
||||
if( pkc )
|
||||
free_public_cert( pkc );
|
||||
if( skc )
|
||||
free_secret_cert( skc );
|
||||
if( upkt )
|
||||
free_user_id( upkt );
|
||||
m_free(uid);
|
||||
m_free(dek);
|
||||
}
|
||||
|
||||
|
107
g10/keyid.c
107
g10/keyid.c
@ -171,3 +171,110 @@ datestr_from_sig( PKT_signature *sig )
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
/**************** .
|
||||
* Return a byte array with the fingerprint for the given PKC/SKC
|
||||
* The length of the array is returned in ret_len. Caller must free
|
||||
* the array.
|
||||
*/
|
||||
byte *
|
||||
fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len )
|
||||
{
|
||||
PKT_public_cert pkc;
|
||||
byte *p;
|
||||
|
||||
pkc.pubkey_algo = skc->pubkey_algo;
|
||||
if( pkc.pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||
pkc.timestamp = skc->timestamp;
|
||||
pkc.valid_days = skc->valid_days;
|
||||
pkc.pubkey_algo = skc->pubkey_algo;
|
||||
pkc.d.elg.p = skc->d.elg.p;
|
||||
pkc.d.elg.g = skc->d.elg.g;
|
||||
pkc.d.elg.y = skc->d.elg.y;
|
||||
}
|
||||
else if( pkc.pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
pkc.d.rsa.rsa_n = skc->d.rsa.rsa_n;
|
||||
pkc.d.rsa.rsa_e = skc->d.rsa.rsa_e;
|
||||
}
|
||||
p = fingerprint_from_pkc( &pkc, ret_len );
|
||||
memset(&pkc, 0, sizeof pkc); /* not really needed */
|
||||
return p;
|
||||
}
|
||||
|
||||
byte *
|
||||
fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len )
|
||||
{
|
||||
byte *p, *buf, *array;
|
||||
size_t len;
|
||||
unsigned n;
|
||||
|
||||
if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||
RMDHANDLE md;
|
||||
const char *dp;
|
||||
|
||||
md = rmd160_open(0);
|
||||
|
||||
{ u32 a = pkc->timestamp;
|
||||
rmd160_putchar( md, a >> 24 );
|
||||
rmd160_putchar( md, a >> 16 );
|
||||
rmd160_putchar( md, a >> 8 );
|
||||
rmd160_putchar( md, a );
|
||||
}
|
||||
{ u16 a = pkc->valid_days;
|
||||
rmd160_putchar( md, a >> 8 );
|
||||
rmd160_putchar( md, a );
|
||||
}
|
||||
rmd160_putchar( md, pkc->pubkey_algo );
|
||||
p = buf = mpi_get_buffer( pkc->d.elg.p, &n, NULL );
|
||||
for( ; !*p && n; p++, n-- )
|
||||
;
|
||||
rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
|
||||
m_free(buf);
|
||||
p = buf = mpi_get_buffer( pkc->d.elg.g, &n, NULL );
|
||||
for( ; !*p && n; p++, n-- )
|
||||
;
|
||||
rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
|
||||
m_free(buf);
|
||||
p = buf = mpi_get_buffer( pkc->d.elg.y, &n, NULL );
|
||||
for( ; !*p && n; p++, n-- )
|
||||
;
|
||||
rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
|
||||
m_free(buf);
|
||||
|
||||
dp = rmd160_final(md);
|
||||
array = m_alloc( 20 );
|
||||
len = 20;
|
||||
memcpy(array, dp, 20 );
|
||||
rmd160_close(md);
|
||||
}
|
||||
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
MD5HANDLE md;
|
||||
|
||||
md = md5_open(0);
|
||||
p = buf = mpi_get_buffer( pkc->d.rsa.rsa_n, &n, NULL );
|
||||
for( ; !*p && n; p++, n-- )
|
||||
;
|
||||
md5_write( md, p, n );
|
||||
m_free(buf);
|
||||
p = buf = mpi_get_buffer( pkc->d.rsa.rsa_e, &n, NULL );
|
||||
for( ; !*p && n; p++, n-- )
|
||||
;
|
||||
md5_write( md, p, n );
|
||||
m_free(buf);
|
||||
md5_final(md);
|
||||
array = m_alloc( 16 );
|
||||
len = 16;
|
||||
memcpy(array, md5_read(md), 16 );
|
||||
md5_close(md);
|
||||
}
|
||||
else {
|
||||
array = m_alloc(1);
|
||||
len = 0; /* ooops */
|
||||
}
|
||||
|
||||
*ret_len = len;
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -342,7 +342,7 @@ proc_plaintext( CTX c, PACKET *pkt )
|
||||
printf("txt: plain text data name='%.*s'\n", pt->namelen, pt->name);
|
||||
free_md_filter_context( &c->mfx );
|
||||
/* fixme: take the digest algo to use from the
|
||||
* onpass_sig packet (if we have these) */
|
||||
* onepass_sig packet (if we have these) */
|
||||
c->mfx.md = md_open(DIGEST_ALGO_RMD160, 0);
|
||||
result = handle_plaintext( pt, &c->mfx );
|
||||
if( !result )
|
||||
@ -450,6 +450,34 @@ print_userid( PACKET *pkt )
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_fingerprint( PKT_public_cert *pkc, PKT_secret_cert *skc )
|
||||
{
|
||||
byte *array, *p;
|
||||
size_t i, n;
|
||||
|
||||
p = array = skc? fingerprint_from_skc( skc, &n )
|
||||
: fingerprint_from_pkc( pkc, &n );
|
||||
printf(" Key fingerprint =");
|
||||
if( n == 20 ) {
|
||||
for(i=0; i < n ; i++, i++, p += 2 ) {
|
||||
if( i == 10 )
|
||||
putchar(' ');
|
||||
printf(" %02X%02X", *p, p[1] );
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(i=0; i < n ; i++, p++ ) {
|
||||
if( i && !(i%8) )
|
||||
putchar(' ');
|
||||
printf(" %02X", *p );
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
m_free(array);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* List the certificate in a user friendly way
|
||||
*/
|
||||
@ -478,6 +506,8 @@ list_node( CTX c, NODE node )
|
||||
printf( "%*s", 31, "" );
|
||||
print_userid( n2->pkt );
|
||||
putchar('\n');
|
||||
if( opt.fingerprint && n2 == node->child )
|
||||
print_fingerprint( pkc, NULL );
|
||||
list_node(c, n2 );
|
||||
}
|
||||
}
|
||||
@ -491,18 +521,20 @@ list_node( CTX c, NODE node )
|
||||
datestr_from_skc( skc ) );
|
||||
n2 = node->child;
|
||||
if( !n2 )
|
||||
printf("ERROR: no user id!");
|
||||
printf("ERROR: no user id!\n");
|
||||
else {
|
||||
print_userid( n2->pkt );
|
||||
putchar('\n');
|
||||
if( opt.fingerprint && n2 == node->child )
|
||||
print_fingerprint( NULL, skc );
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
else if( node->pkt->pkttype == PKT_USER_ID ) {
|
||||
/* list everything under this user id */
|
||||
for(n2=node->child; n2; n2 = n2->next )
|
||||
list_node(c, n2 );
|
||||
}
|
||||
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
PKT_signature *sig = node->pkt->pkt.signature;
|
||||
int rc2;
|
||||
size_t n;
|
||||
@ -510,6 +542,9 @@ list_node( CTX c, NODE node )
|
||||
int sigrc = ' ';
|
||||
|
||||
assert( !node->child );
|
||||
if( !opt.list_sigs )
|
||||
return;
|
||||
|
||||
if( opt.check_sigs ) {
|
||||
|
||||
switch( (rc2=do_check_sig( c, node )) ) {
|
||||
|
@ -32,8 +32,8 @@ struct {
|
||||
int answer_no; /* answer no on most questions */
|
||||
int check_sigs; /* check key signatures */
|
||||
int cache_all;
|
||||
int detached_sig;
|
||||
int reserved3;
|
||||
int fingerprint; /* list fingerprints */
|
||||
int list_sigs; /* list signatures */
|
||||
int reserved4;
|
||||
int reserved5;
|
||||
int reserved6;
|
||||
|
@ -124,7 +124,6 @@ typedef struct {
|
||||
MPI rsa_q; /* secret second prime number */
|
||||
MPI rsa_u; /* secret multiplicative inverse */
|
||||
u16 csum; /* checksum */
|
||||
u16 calc_csum; /* and a place to store the calculated csum */
|
||||
byte is_protected; /* The above infos are protected and must */
|
||||
/* be decrypteded before use */
|
||||
byte protect_algo; /* cipher used to protect the secret informations*/
|
||||
@ -142,7 +141,6 @@ typedef struct {
|
||||
MPI y; /* g^x mod p */
|
||||
MPI x; /* secret exponent */
|
||||
u16 csum; /* checksum */
|
||||
u16 calc_csum; /* and a place to store the calculated csum */
|
||||
byte is_protected; /* The above infos are protected and must */
|
||||
/* be decrypteded before use */
|
||||
byte protect_algo; /* cipher used to protect the secret informations*/
|
||||
@ -220,6 +218,7 @@ int parse_packet( IOBUF inp, PACKET *ret_pkt);
|
||||
/*-- build-packet.c --*/
|
||||
int build_packet( IOBUF inp, PACKET *pkt );
|
||||
u32 calc_packet_length( PACKET *pkt );
|
||||
void hash_public_cert( MD_HANDLE *md, PKT_public_cert *pkc );
|
||||
|
||||
/*-- free-packet.c --*/
|
||||
void free_pubkey_enc( PKT_pubkey_enc *enc );
|
||||
@ -238,6 +237,7 @@ int signature_check( PKT_signature *sig, MD_HANDLE *digest );
|
||||
|
||||
/*-- seckey-cert.c --*/
|
||||
int check_secret_key( PKT_secret_cert *cert );
|
||||
int protect_secret_key( PKT_secret_cert *cert, DEK *dek );
|
||||
|
||||
/*-- pubkey-enc.c --*/
|
||||
int get_session_key( PKT_pubkey_enc *k, DEK *dek );
|
||||
@ -256,5 +256,9 @@ int ask_for_detached_datafile( md_filter_context_t *mfx );
|
||||
/*-- comment.c --*/
|
||||
int write_comment( IOBUF out, const char *s );
|
||||
|
||||
/*-- sign.c --*/
|
||||
int make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
|
||||
PKT_user_id *uid, PKT_secret_cert *skc,
|
||||
int sigclass, int digest_algo );
|
||||
|
||||
#endif /*G10_PACKET_H*/
|
||||
|
@ -239,8 +239,8 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
|
||||
k->keyid[0], k->keyid[1]);
|
||||
if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||
n = pktlen;
|
||||
k->d.elg.a = mpi_decode(inp, &n ); pktlen -=n;
|
||||
k->d.elg.b = mpi_decode(inp, &n ); pktlen -=n;
|
||||
k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n;
|
||||
k->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
|
||||
if( list_mode ) {
|
||||
printf("\telg a: ");
|
||||
mpi_print(stdout, k->d.elg.a, mpi_print_mode );
|
||||
@ -251,7 +251,7 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
|
||||
}
|
||||
else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
n = pktlen;
|
||||
k->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n;
|
||||
k->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
|
||||
if( list_mode ) {
|
||||
printf("\trsa integer: ");
|
||||
mpi_print(stdout, k->d.rsa.rsa_integer, mpi_print_mode );
|
||||
@ -304,8 +304,8 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
sig->d.elg.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
|
||||
sig->d.elg.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
|
||||
n = pktlen;
|
||||
sig->d.elg.a = mpi_decode(inp, &n ); pktlen -=n;
|
||||
sig->d.elg.b = mpi_decode(inp, &n ); pktlen -=n;
|
||||
sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n;
|
||||
sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
|
||||
if( list_mode ) {
|
||||
printf("\tdigest algo %d, begin of digest %02x %02x\n",
|
||||
sig->d.elg.digest_algo,
|
||||
@ -313,7 +313,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
printf("\telg a: ");
|
||||
mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
|
||||
printf("\n\telg b: ");
|
||||
mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
|
||||
mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
@ -326,7 +326,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
sig->d.rsa.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
|
||||
sig->d.rsa.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
|
||||
n = pktlen;
|
||||
sig->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n;
|
||||
sig->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
|
||||
if( list_mode ) {
|
||||
printf("\tdigest algo %d, begin of digest %02x %02x\n",
|
||||
sig->d.rsa.digest_algo,
|
||||
@ -439,9 +439,9 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
|
||||
if( algorithm == PUBKEY_ALGO_ELGAMAL ) {
|
||||
MPI elg_p, elg_g, elg_y;
|
||||
n = pktlen; elg_p = mpi_decode(inp, &n ); pktlen -=n;
|
||||
n = pktlen; elg_g = mpi_decode(inp, &n ); pktlen -=n;
|
||||
n = pktlen; elg_y = mpi_decode(inp, &n ); pktlen -=n;
|
||||
n = pktlen; elg_p = mpi_read(inp, &n, 0 ); pktlen -=n;
|
||||
n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n;
|
||||
n = pktlen; elg_y = mpi_read(inp, &n, 0 ); pktlen -=n;
|
||||
if( list_mode ) {
|
||||
printf( "\telg p: ");
|
||||
mpi_print(stdout, elg_p, mpi_print_mode );
|
||||
@ -483,32 +483,24 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
else
|
||||
cert->d.elg.is_protected = 0;
|
||||
|
||||
n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
|
||||
cert->d.elg.x = (MPI)mpibuf;
|
||||
n = pktlen; cert->d.elg.x = mpi_read(inp, &n, 1 ); pktlen -=n;
|
||||
|
||||
cert->d.elg.csum = read_16(inp); pktlen -= 2;
|
||||
cert->d.elg.calc_csum = 0;
|
||||
if( list_mode ) {
|
||||
printf("\t[secret value x is not shown]\n"
|
||||
"\tchecksum: %04hx\n", cert->d.elg.csum);
|
||||
}
|
||||
if( !cert->d.elg.is_protected ) { /* convert buffer to MPIs */
|
||||
mpibuf = (byte*)cert->d.elg.x;
|
||||
cert->d.elg.calc_csum += checksum( mpibuf );
|
||||
cert->d.elg.x = mpi_decode_buffer( mpibuf );
|
||||
m_free( mpibuf );
|
||||
/*log_mpidump("elg p=", cert->d.elg.p );
|
||||
log_mpidump("elg g=", cert->d.elg.g );
|
||||
log_mpidump("elg y=", cert->d.elg.y );
|
||||
log_mpidump("elg x=", cert->d.elg.x ); */
|
||||
}
|
||||
/*log_mpidump("elg p=", cert->d.elg.p );
|
||||
log_mpidump("elg g=", cert->d.elg.g );
|
||||
log_mpidump("elg y=", cert->d.elg.y );
|
||||
log_mpidump("elg x=", cert->d.elg.x ); */
|
||||
}
|
||||
}
|
||||
else if( algorithm == PUBKEY_ALGO_RSA ) {
|
||||
MPI rsa_pub_mod, rsa_pub_exp;
|
||||
|
||||
n = pktlen; rsa_pub_mod = mpi_decode(inp, &n ); pktlen -=n;
|
||||
n = pktlen; rsa_pub_exp = mpi_decode(inp, &n ); pktlen -=n;
|
||||
n = pktlen; rsa_pub_mod = mpi_read(inp, &n, 0); pktlen -=n;
|
||||
n = pktlen; rsa_pub_exp = mpi_read(inp, &n, 0 ); pktlen -=n;
|
||||
if( list_mode ) {
|
||||
printf( "\tpublic modulus n: ");
|
||||
mpi_print(stdout, rsa_pub_mod, mpi_print_mode );
|
||||
@ -546,43 +538,22 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
else
|
||||
cert->d.rsa.is_protected = 0;
|
||||
|
||||
n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
|
||||
cert->d.rsa.rsa_d = (MPI)mpibuf;
|
||||
|
||||
n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
|
||||
cert->d.rsa.rsa_p = (MPI)mpibuf;
|
||||
|
||||
n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
|
||||
cert->d.rsa.rsa_q = (MPI)mpibuf;
|
||||
|
||||
n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
|
||||
cert->d.rsa.rsa_u = (MPI)mpibuf;
|
||||
n = pktlen; cert->d.rsa.rsa_d = mpi_read(inp, &n, 1 ); pktlen -=n;
|
||||
n = pktlen; cert->d.rsa.rsa_p = mpi_read(inp, &n, 1 ); pktlen -=n;
|
||||
n = pktlen; cert->d.rsa.rsa_q = mpi_read(inp, &n, 1 ); pktlen -=n;
|
||||
n = pktlen; cert->d.rsa.rsa_u = mpi_read(inp, &n, 1 ); pktlen -=n;
|
||||
|
||||
cert->d.rsa.csum = read_16(inp); pktlen -= 2;
|
||||
cert->d.rsa.calc_csum = 0;
|
||||
if( list_mode ) {
|
||||
printf("\t[secret values d,p,q,u are not shown]\n"
|
||||
"\tchecksum: %04hx\n", cert->d.rsa.csum);
|
||||
}
|
||||
if( !cert->d.rsa.is_protected ) { /* convert buffer to MPIs */
|
||||
#define X(a) do { \
|
||||
mpibuf = (byte*)cert->d.rsa.rsa_##a; \
|
||||
cert->d.rsa.calc_csum += checksum( mpibuf ); \
|
||||
cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf ); \
|
||||
m_free( mpibuf ); \
|
||||
} while(0)
|
||||
X(d);
|
||||
X(p);
|
||||
X(q);
|
||||
X(u);
|
||||
#undef X
|
||||
/* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
|
||||
log_mpidump("rsa e=", cert->d.rsa.rsa_e );
|
||||
log_mpidump("rsa d=", cert->d.rsa.rsa_d );
|
||||
log_mpidump("rsa p=", cert->d.rsa.rsa_p );
|
||||
log_mpidump("rsa q=", cert->d.rsa.rsa_q );
|
||||
log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
|
||||
}
|
||||
/* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
|
||||
log_mpidump("rsa e=", cert->d.rsa.rsa_e );
|
||||
log_mpidump("rsa d=", cert->d.rsa.rsa_d );
|
||||
log_mpidump("rsa p=", cert->d.rsa.rsa_p );
|
||||
log_mpidump("rsa q=", cert->d.rsa.rsa_q );
|
||||
log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
|
||||
}
|
||||
}
|
||||
else if( list_mode )
|
||||
@ -671,34 +642,9 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
|
||||
1 = "we do not trust this key's ownership"
|
||||
2 = "we have marginal confidence of this key's ownership"
|
||||
3 = "we completely trust this key's ownership."
|
||||
/* This one (3) requires either:
|
||||
* - 1 ultimately trusted signature (SIGTRUST=7)
|
||||
* - COMPLETES_NEEDED completely trusted signatures (SIGTRUST=6)
|
||||
* - MARGINALS_NEEDED marginally trusted signatures (SIGTRUST=5)
|
||||
*/
|
||||
if( c & 0x80 )
|
||||
"warnonly"
|
||||
else if( prev_packet_is_a_signature ) {
|
||||
Bits 0-2 - SIGTRUST bits - Trust bits for this signature. Value is
|
||||
copied directly from OWNERTRUST bits of signer:
|
||||
000 - undefined, or uninitialized trust.
|
||||
001 - unknown
|
||||
010 - We do not trust this signature.
|
||||
011 - reserved
|
||||
100 - reserved
|
||||
101 - We reasonably trust this signature.
|
||||
110 - We completely trust this signature.
|
||||
111 - ultimately trusted signature (from the owner of the ring)
|
||||
Bit 6 - CHECKED bit - This means that the key checking pass (pgp -kc,
|
||||
also invoked automatically whenever keys are added to the
|
||||
keyring) has tested this signature and found it good. If
|
||||
this bit is not set, the maintenance pass considers this
|
||||
signature untrustworthy.
|
||||
Bit 7 - CONTIG bit - Means this signature leads up a contiguous trusted
|
||||
certification path all the way back to the ultimately-
|
||||
trusted keyring owner, where the buck stops. This bit is derived
|
||||
from other trust packets. It is currently not used for anything
|
||||
in PGP.
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -44,13 +44,13 @@ get_passphrase_hash( u32 *keyid, char *text )
|
||||
DEK *dek;
|
||||
|
||||
if( keyid ) {
|
||||
tty_printf("Need a pass phrase to unlock the secret key!\n");
|
||||
tty_printf("\nNeed a pass phrase to unlock the secret key!\n");
|
||||
tty_printf("KeyID: %08lX\n\n", keyid[1] );
|
||||
}
|
||||
if( keyid && (p=getenv("PGPPATHPHRASE")) ) {
|
||||
if( keyid && (p=getenv("G10PASSPHRASE")) ) {
|
||||
pw = m_alloc_secure(strlen(p)+1);
|
||||
strcpy(pw,p);
|
||||
tty_printf("Taking it from $PGPPATHPHRASE !\n", keyid[1] );
|
||||
tty_printf("Taking it from $G10PASSPHRASE !\n", keyid[1] );
|
||||
}
|
||||
else
|
||||
pw = tty_get_hidden("Enter pass phrase: " );
|
||||
@ -61,7 +61,7 @@ get_passphrase_hash( u32 *keyid, char *text )
|
||||
m_free(pw); /* is allocated in secure memory, so it will be burned */
|
||||
if( !p ) {
|
||||
tty_kill_prompt();
|
||||
tty_printf("\n\n");
|
||||
tty_printf("\n");
|
||||
}
|
||||
return dek;
|
||||
}
|
||||
@ -70,6 +70,7 @@ get_passphrase_hash( u32 *keyid, char *text )
|
||||
/****************
|
||||
* This function is used to construct a DEK from a user input.
|
||||
* It uses the default CIPHER
|
||||
* Returns: 0 = okay, -1 No passphrase entered, > 0 error
|
||||
*/
|
||||
int
|
||||
make_dek_from_passphrase( DEK *dek, int mode )
|
||||
@ -88,7 +89,10 @@ make_dek_from_passphrase( DEK *dek, int mode )
|
||||
}
|
||||
m_free(pw2);
|
||||
}
|
||||
rc = hash_passphrase( dek, pw );
|
||||
if( !*pw )
|
||||
rc = -1;
|
||||
else
|
||||
rc = hash_passphrase( dek, pw );
|
||||
m_free(pw);
|
||||
return rc;
|
||||
}
|
||||
|
@ -35,12 +35,20 @@
|
||||
#endif
|
||||
|
||||
static u16
|
||||
checksum( byte *p )
|
||||
checksum_u16( unsigned n )
|
||||
{
|
||||
u16 n, a;
|
||||
u16 a;
|
||||
|
||||
a = (n >> 8) & 0xff;
|
||||
a |= n & 0xff;
|
||||
return a;
|
||||
}
|
||||
|
||||
static u16
|
||||
checksum( byte *p, unsigned n )
|
||||
{
|
||||
u16 a;
|
||||
|
||||
n = *p++ << 8;
|
||||
n |= *p++;
|
||||
for(a=0; n; n-- )
|
||||
a += *p++;
|
||||
return a;
|
||||
@ -51,16 +59,16 @@ checksum( byte *p )
|
||||
static int
|
||||
check_elg( PKT_secret_cert *cert )
|
||||
{
|
||||
byte iv[8];
|
||||
byte *mpibuf;
|
||||
u16 n;
|
||||
MPI temp_mpi;
|
||||
byte *buffer;
|
||||
u16 n, csum=0;
|
||||
int res;
|
||||
unsigned nbytes;
|
||||
u32 keyid[2];
|
||||
ELG_secret_key skey;
|
||||
|
||||
if( cert->d.elg.is_protected ) { /* remove the protection */
|
||||
DEK *dek = NULL;
|
||||
MPI test_x;
|
||||
BLOWFISH_context *blowfish_ctx=NULL;
|
||||
|
||||
switch( cert->d.elg.protect_algo ) {
|
||||
@ -68,47 +76,87 @@ check_elg( PKT_secret_cert *cert )
|
||||
case CIPHER_ALGO_BLOWFISH:
|
||||
keyid_from_skc( cert, keyid );
|
||||
dek = get_passphrase_hash( keyid, NULL );
|
||||
m_free(dek); /* pw is in secure memory, so m_free() burns it */
|
||||
memset( iv, 0, BLOWFISH_BLOCKSIZE );
|
||||
blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
|
||||
blowfish_setiv( blowfish_ctx, iv );
|
||||
blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
|
||||
m_free(dek); /* pw is in secure memory, so m_free() burns it */
|
||||
blowfish_setiv( blowfish_ctx, NULL );
|
||||
blowfish_decode_cfb( blowfish_ctx,
|
||||
cert->d.elg.protect.blowfish.iv,
|
||||
cert->d.elg.protect.blowfish.iv, 8 );
|
||||
cert->d.elg.calc_csum = 0;
|
||||
mpibuf = (byte*)cert->d.elg.x;
|
||||
n = ((mpibuf[0] << 8) | mpibuf[1])-2;
|
||||
blowfish_decode_cfb( blowfish_ctx, mpibuf+4, mpibuf+4, n );
|
||||
cert->d.elg.calc_csum += checksum( mpibuf );
|
||||
cert->d.elg.x = mpi_decode_buffer( mpibuf );
|
||||
m_free( mpibuf );
|
||||
buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
|
||||
csum = checksum_u16( nbytes*8 );
|
||||
blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
|
||||
csum += checksum( buffer, nbytes );
|
||||
test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.elg.x) );
|
||||
mpi_set_buffer( test_x, buffer, nbytes, 0 );
|
||||
m_free( buffer );
|
||||
m_free( blowfish_ctx );
|
||||
cert->d.elg.is_protected = 0;
|
||||
/* now let's see wether we have used the right passphrase */
|
||||
if( cert->d.elg.calc_csum != cert->d.elg.csum )
|
||||
if( csum != cert->d.elg.csum ) {
|
||||
mpi_free(test_x);
|
||||
return G10ERR_BAD_PASS;
|
||||
}
|
||||
|
||||
skey.p = cert->d.elg.p;
|
||||
skey.g = cert->d.elg.g;
|
||||
skey.y = cert->d.elg.y;
|
||||
skey.x = cert->d.elg.x;
|
||||
skey.x = test_x;
|
||||
res = elg_check_secret_key( &skey );
|
||||
memset( &skey, 0, sizeof skey );
|
||||
if( !res )
|
||||
if( !res ) {
|
||||
mpi_free(test_x);
|
||||
return G10ERR_BAD_PASS;
|
||||
}
|
||||
mpi_set(cert->d.elg.x, test_x);
|
||||
mpi_free(test_x);
|
||||
cert->d.elg.is_protected = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
|
||||
}
|
||||
}
|
||||
/* must check the checksum here, because we didn't do it when
|
||||
* parsing an unprotected certificate */
|
||||
if( cert->d.elg.calc_csum != cert->d.elg.csum ) {
|
||||
log_error("checksum in secret key certificate is wrong\n");
|
||||
log_debug("stored csum=%04hx calculated csum=%04hx\n",
|
||||
cert->d.elg.csum, cert->d.elg.calc_csum );
|
||||
return G10ERR_CHECKSUM;
|
||||
else { /* not protected */
|
||||
buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
|
||||
csum = checksum_u16( nbytes*8 );
|
||||
csum += checksum( buffer, nbytes );
|
||||
m_free( buffer );
|
||||
if( csum != cert->d.elg.csum )
|
||||
return G10ERR_CHECKSUM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
protect_elg( PKT_secret_cert *cert, DEK *dek )
|
||||
{
|
||||
byte *buffer;
|
||||
unsigned nbytes;
|
||||
|
||||
if( !cert->d.elg.is_protected ) { /* add the protection */
|
||||
BLOWFISH_context *blowfish_ctx=NULL;
|
||||
|
||||
switch( cert->d.elg.protect_algo ) {
|
||||
case CIPHER_ALGO_NONE: log_bug(NULL); break;
|
||||
case CIPHER_ALGO_BLOWFISH:
|
||||
blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
|
||||
blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
|
||||
blowfish_setiv( blowfish_ctx, NULL );
|
||||
blowfish_encode_cfb( blowfish_ctx,
|
||||
cert->d.elg.protect.blowfish.iv,
|
||||
cert->d.elg.protect.blowfish.iv, 8 );
|
||||
buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
|
||||
blowfish_encode_cfb( blowfish_ctx, buffer, buffer, nbytes );
|
||||
mpi_set_buffer( cert->d.elg.x, buffer, nbytes, 0 );
|
||||
m_free( buffer );
|
||||
m_free( blowfish_ctx );
|
||||
cert->d.elg.is_protected = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -118,80 +166,86 @@ check_elg( PKT_secret_cert *cert )
|
||||
static int
|
||||
check_rsa( PKT_secret_cert *cert )
|
||||
{
|
||||
byte iv[8];
|
||||
byte *mpibuf;
|
||||
u16 n;
|
||||
MPI temp_mpi;
|
||||
byte *buffer;
|
||||
u16 n, csum=0;
|
||||
int res;
|
||||
unsigned nbytes;
|
||||
u32 keyid[2];
|
||||
RSA_secret_key skey;
|
||||
|
||||
if( cert->d.rsa.is_protected ) { /* remove the protection */
|
||||
DEK *dek = NULL;
|
||||
BLOWFISH_context *blowfish_ctx=NULL;
|
||||
|
||||
switch( cert->d.rsa.protect_algo ) {
|
||||
case CIPHER_ALGO_NONE:
|
||||
log_bug("unprotect secret_cert is flagged protected\n");
|
||||
break;
|
||||
/* FIXME: use test variables to check for the correct key */
|
||||
case CIPHER_ALGO_NONE: log_bug(NULL); break;
|
||||
case CIPHER_ALGO_BLOWFISH:
|
||||
keyid_from_skc( cert, keyid );
|
||||
dek = get_passphrase_hash( keyid, NULL );
|
||||
|
||||
m_free(dek); /* pw is in secure memory, so m_free() burns it */
|
||||
memset( iv, 0, BLOWFISH_BLOCKSIZE );
|
||||
blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
|
||||
blowfish_setiv( blowfish_ctx, iv );
|
||||
blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
|
||||
m_free(dek); /* pw is in secure memory, so m_free() burns it */
|
||||
blowfish_setiv( blowfish_ctx, NULL );
|
||||
blowfish_decode_cfb( blowfish_ctx,
|
||||
cert->d.rsa.protect.blowfish.iv,
|
||||
cert->d.rsa.protect.blowfish.iv, 8 );
|
||||
cert->d.rsa.calc_csum = 0;
|
||||
#define X(a) do { \
|
||||
mpibuf = (byte*)cert->d.rsa.rsa_##a; \
|
||||
n = ((mpibuf[0] << 8) | mpibuf[1])-2; \
|
||||
blowfish_decode_cfb( blowfish_ctx, \
|
||||
mpibuf+4, mpibuf+4, n ); \
|
||||
cert->d.rsa.calc_csum += checksum( mpibuf ); \
|
||||
cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf ); \
|
||||
m_free( mpibuf ); \
|
||||
} while(0)
|
||||
csum = 0;
|
||||
#define X(a) do { \
|
||||
buffer = mpi_get_buffer( cert->d.rsa.rsa_##a, &nbytes, NULL );\
|
||||
csum += checksum_u16( nbytes*8 ); \
|
||||
blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes ); \
|
||||
csum += checksum( buffer, nbytes ); \
|
||||
mpi_set_buffer(cert->d.rsa.rsa_##a, buffer, nbytes, 0 ); \
|
||||
m_free( buffer ); \
|
||||
} while(0)
|
||||
X(d);
|
||||
X(p);
|
||||
X(q);
|
||||
X(u);
|
||||
#undef X
|
||||
m_free( blowfish_ctx );
|
||||
cert->d.rsa.is_protected = 0;
|
||||
#if 0
|
||||
#define X(a) do { printf("\tRSA " #a ": "); \
|
||||
mpi_print(stdout, cert->d.rsa.rsa_##a, 1 ); \
|
||||
putchar('\n'); \
|
||||
} while(0)
|
||||
X(n); X(e); X(d); X(p); X(q); X(u);
|
||||
#undef X
|
||||
#endif
|
||||
cert->d.rsa.is_protected = 0;
|
||||
m_free( blowfish_ctx );
|
||||
/* now let's see wether we have used the right passphrase */
|
||||
if( cert->d.rsa.calc_csum != cert->d.rsa.csum )
|
||||
if( csum != cert->d.rsa.csum )
|
||||
return G10ERR_BAD_PASS;
|
||||
temp_mpi = mpi_alloc(40);
|
||||
mpi_mul(temp_mpi, cert->d.rsa.rsa_p, cert->d.rsa.rsa_q );
|
||||
res = mpi_cmp( temp_mpi, cert->d.rsa.rsa_n );
|
||||
mpi_free(temp_mpi);
|
||||
if( res )
|
||||
|
||||
skey.d = cert->d.rsa.rsa_d;
|
||||
skey.p = cert->d.rsa.rsa_p;
|
||||
skey.q = cert->d.rsa.rsa_q;
|
||||
skey.u = cert->d.rsa.rsa_u;
|
||||
res = rsa_check_secret_key( &skey );
|
||||
memset( &skey, 0, sizeof skey );
|
||||
if( !res )
|
||||
return G10ERR_BAD_PASS;
|
||||
break;
|
||||
|
||||
default:
|
||||
return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
|
||||
return G10ERR_CIPHER_ALGO; /* unsupported protection algorithm */
|
||||
}
|
||||
}
|
||||
/* must check the checksum here, because we didn't do it when
|
||||
* parsing an unprotected certificate */
|
||||
if( cert->d.rsa.calc_csum != cert->d.rsa.csum ) {
|
||||
log_error("checksum in secret key certificate is wrong\n");
|
||||
log_debug("stored csum=%04hx calculated csum=%04hx\n",
|
||||
cert->d.rsa.csum, cert->d.rsa.calc_csum );
|
||||
return G10ERR_CHECKSUM;
|
||||
else { /* not protected */
|
||||
csum =0;
|
||||
buffer = mpi_get_buffer( cert->d.rsa.rsa_d, &nbytes, NULL );
|
||||
csum += checksum_u16( nbytes*8 );
|
||||
csum += checksum( buffer, nbytes );
|
||||
m_free( buffer );
|
||||
buffer = mpi_get_buffer( cert->d.rsa.rsa_p, &nbytes, NULL );
|
||||
csum += checksum_u16( nbytes*8 );
|
||||
csum += checksum( buffer, nbytes );
|
||||
m_free( buffer );
|
||||
buffer = mpi_get_buffer( cert->d.rsa.rsa_q, &nbytes, NULL );
|
||||
csum += checksum_u16( nbytes*8 );
|
||||
csum += checksum( buffer, nbytes );
|
||||
m_free( buffer );
|
||||
buffer = mpi_get_buffer( cert->d.rsa.rsa_u, &nbytes, NULL );
|
||||
csum += checksum_u16( nbytes*8 );
|
||||
csum += checksum( buffer, nbytes );
|
||||
m_free( buffer );
|
||||
if( csum != cert->d.rsa.csum )
|
||||
return G10ERR_CHECKSUM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /*HAVE_RSA_CIPHER*/
|
||||
@ -201,15 +255,44 @@ check_rsa( PKT_secret_cert *cert )
|
||||
|
||||
/****************
|
||||
* Check the secret key certificate
|
||||
* Ask up to 3 time for a correct passphrase
|
||||
*/
|
||||
int
|
||||
check_secret_key( PKT_secret_cert *cert )
|
||||
{
|
||||
int rc = G10ERR_BAD_PASS;
|
||||
int i;
|
||||
|
||||
for(i=0; i < 3 && rc == G10ERR_BAD_PASS; i++ ) {
|
||||
if( i )
|
||||
log_error("Invalid passphrase; please try again ...\n");
|
||||
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
|
||||
rc = check_elg( cert );
|
||||
#ifdef HAVE_RSA_CIPHER
|
||||
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
|
||||
rc = check_rsa( cert );
|
||||
#endif
|
||||
else
|
||||
rc = G10ERR_PUBKEY_ALGO;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Protect the secret key certificate with the passphrase from DEK
|
||||
*/
|
||||
int
|
||||
protect_secret_key( PKT_secret_cert *cert, DEK *dek )
|
||||
{
|
||||
if( !dek )
|
||||
return 0;
|
||||
|
||||
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
|
||||
return check_elg( cert );
|
||||
#ifdef HAVE_RSA_CIPHER
|
||||
return protect_elg( cert, dek );
|
||||
#ifdef 0 /* noy yet implemented */
|
||||
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
|
||||
return check_rsa( cert );
|
||||
return protect_rsa( cert, dek );
|
||||
#endif
|
||||
else
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
|
@ -212,3 +212,5 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest )
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -49,5 +49,6 @@
|
||||
#define G10ERR_NI_PUBKEY 27
|
||||
#define G10ERR_NI_CIPHER 28
|
||||
#define G10ERR_SIG_CLASS 29
|
||||
#define G10ERR_BAD_MPI 30
|
||||
|
||||
#endif /*G10_ERRORS_H*/
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define m_realloc(n,m) m_debug_realloc((n),(m), M_DBGINFO(__LINE__) )
|
||||
#define m_free(n) m_debug_free((n), M_DBGINFO(__LINE__) )
|
||||
#define m_check(n) m_debug_check((n), M_DBGINFO(__LINE__) )
|
||||
#define m_copy(a) m_debug_copy((a), M_DBGINFO(__LINE__) )
|
||||
|
||||
void *m_debug_alloc( size_t n, const char *info );
|
||||
void *m_debug_alloc_clear( size_t n, const char *info );
|
||||
@ -41,6 +42,7 @@ void *m_debug_alloc_secure_clear( size_t n, const char *info );
|
||||
void *m_debug_realloc( void *a, size_t n, const char *info );
|
||||
void m_debug_free( void *p, const char *info );
|
||||
void m_debug_check( const void *a, const char *info );
|
||||
void *m_debug_copy( const void *a, const char *info );
|
||||
|
||||
#else
|
||||
void *m_alloc( size_t n );
|
||||
@ -50,6 +52,7 @@ void *m_alloc_secure_clear( size_t n );
|
||||
void *m_realloc( void *a, size_t n );
|
||||
void m_free( void *p );
|
||||
void m_check( const void *a );
|
||||
void *m_copy( void *a );
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -52,15 +52,16 @@ int mpi_debug_mode;
|
||||
typedef struct mpi_struct {
|
||||
int alloced; /* array size (# of allocated limbs) */
|
||||
int nlimbs; /* number of valid limbs */
|
||||
int nbits; /* the real number of valid bits (info only) */
|
||||
int sign; /* indicates a negative number */
|
||||
int secure; /* array mut be allocated in secure memory space */
|
||||
int secure; /* array must be allocated in secure memory space */
|
||||
mpi_limb_t *d; /* array with the limbs */
|
||||
} *MPI;
|
||||
|
||||
#define MPI_NULL NULL
|
||||
|
||||
#define mpi_get_nlimbs(a) ((a)->nlimbs)
|
||||
#define mpi_is_neg(a) ((a)->sign)
|
||||
#define mpi_get_nlimbs(a) ((a)->nlimbs)
|
||||
#define mpi_is_neg(a) ((a)->sign)
|
||||
|
||||
/*-- mpiutil.c --*/
|
||||
|
||||
@ -90,23 +91,18 @@ void mpi_m_check( MPI a );
|
||||
void mpi_swap( MPI a, MPI b);
|
||||
|
||||
/*-- mpicoder.c --*/
|
||||
int mpi_encode( IOBUF out, MPI a );
|
||||
int mpi_encode_csum( IOBUF out, MPI a, u16 *csum );
|
||||
int mpi_write( IOBUF out, byte *a);
|
||||
int mpi_write_csum( IOBUF out, byte *a, u16 *csum);
|
||||
int mpi_write( IOBUF out, MPI a );
|
||||
#ifdef M_DEBUG
|
||||
#define mpi_decode(a,b) mpi_debug_decode((a),(b), M_DBGINFO( __LINE__ ) )
|
||||
#define mpi_decode_buffer(a) mpi_debug_decode_buffer((a), M_DBGINFO( __LINE__ ) )
|
||||
MPI mpi_debug_decode(IOBUF inp, unsigned *nread, const char *info);
|
||||
MPI mpi_debug_decode_buffer(byte *buffer, const char *info );
|
||||
#define mpi_read(a,b,c) mpi_debug_read((a),(b),(c), M_DBGINFO( __LINE__ ) )
|
||||
MPI mpi_debug_read(IOBUF inp, unsigned *nread, int secure, const char *info);
|
||||
#else
|
||||
MPI mpi_decode(IOBUF inp, unsigned *nread);
|
||||
MPI mpi_decode_buffer(byte *buffer );
|
||||
MPI mpi_read(IOBUF inp, unsigned *nread, int secure);
|
||||
#endif
|
||||
byte *mpi_read(IOBUF inp, unsigned *ret_nread);
|
||||
int mpi_fromstr(MPI val, const char *str);
|
||||
int mpi_print( FILE *fp, MPI a, int mode );
|
||||
u32 mpi_get_keyid( MPI a, u32 *keyid );
|
||||
byte *mpi_get_buffer( MPI a, unsigned *nbytes, int *sign );
|
||||
void mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign );
|
||||
|
||||
/*-- mpi-add.c --*/
|
||||
void mpi_add_ui(MPI w, MPI u, ulong v );
|
||||
|
286
mpi/mpicoder.c
286
mpi/mpicoder.c
@ -24,13 +24,13 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mpi-internal.h"
|
||||
#include "iobuf.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef M_DEBUG
|
||||
#undef mpi_decode
|
||||
#undef mpi_decode_buffer
|
||||
#undef mpi_read
|
||||
#endif
|
||||
|
||||
#define MAX_EXTERN_MPI_BITS 16384
|
||||
@ -39,89 +39,52 @@
|
||||
* write an mpi to out.
|
||||
*/
|
||||
int
|
||||
mpi_encode( IOBUF out, MPI a )
|
||||
{
|
||||
u16 dummy;
|
||||
return mpi_encode_csum( out, a, &dummy );
|
||||
}
|
||||
|
||||
int
|
||||
mpi_encode_csum( IOBUF out, MPI a, u16 *csum )
|
||||
mpi_write( IOBUF out, MPI a )
|
||||
{
|
||||
int i;
|
||||
byte c;
|
||||
unsigned nbits = a->nlimbs * BITS_PER_MPI_LIMB;
|
||||
mpi_limb_t limb;
|
||||
|
||||
#if BYTES_PER_MPI_LIMB != 4
|
||||
#error Make this function work with other LIMB sizes
|
||||
#endif
|
||||
/* fixme: use a->nbits if valid */
|
||||
if( nbits > MAX_EXTERN_MPI_BITS )
|
||||
log_bug("mpi_encode: mpi too large (%u bits)\n", nbits);
|
||||
iobuf_put(out, (c=nbits >>8) ); *csum += c;
|
||||
iobuf_put(out, (c=nbits) ); *csum += c;
|
||||
iobuf_put(out, (nbits >>8) );
|
||||
iobuf_put(out, (nbits) );
|
||||
for(i=a->nlimbs-1; i >= 0; i-- ) {
|
||||
limb = a->d[i];
|
||||
iobuf_put(out, (c=limb >> 24) ); *csum += c;
|
||||
iobuf_put(out, (c=limb >> 16) ); *csum += c;
|
||||
iobuf_put(out, (c=limb >> 8) ); *csum += c;
|
||||
iobuf_put(out, (c=limb ) ); *csum += c;
|
||||
#if BYTES_PER_MPI_LIMB == 4
|
||||
iobuf_put(out, (limb >> 24) );
|
||||
iobuf_put(out, (limb >> 16) );
|
||||
iobuf_put(out, (limb >> 8) );
|
||||
iobuf_put(out, (limb ) );
|
||||
#elif BYTES_PER_MPI_LIMB == 8
|
||||
iobuf_put(out, (limb >> 56) );
|
||||
iobuf_put(out, (limb >> 48) );
|
||||
iobuf_put(out, (limb >> 40) );
|
||||
iobuf_put(out, (limb >> 32) );
|
||||
iobuf_put(out, (limb >> 24) );
|
||||
iobuf_put(out, (limb >> 16) );
|
||||
iobuf_put(out, (limb >> 8) );
|
||||
iobuf_put(out, (limb ) );
|
||||
#else
|
||||
#error Make this function work with other LIMB sizes
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* encode the MPI into a newly allocated buffer, the buffer is
|
||||
* so constructed, that it can be used for mpi_write. The caller
|
||||
* must free the returned buffer. The buffer is allocated in the same
|
||||
* type of memory space as A is.
|
||||
*/
|
||||
byte *
|
||||
mpi_encode_buffer( MPI a )
|
||||
{
|
||||
abort();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************
|
||||
* write an mpi to out. This is a special function to handle
|
||||
* encrypted values. It simply writes the buffer a to OUT.
|
||||
* A is a special buffer, starting with 2 bytes giving it's length
|
||||
* (in big endian order) and 2 bytes giving it's length in bits (also
|
||||
* big endian)
|
||||
*/
|
||||
int
|
||||
mpi_write( IOBUF out, byte *a)
|
||||
{
|
||||
u16 dummy;
|
||||
return mpi_write_csum( out, a, &dummy );
|
||||
}
|
||||
|
||||
int
|
||||
mpi_write_csum( IOBUF out, byte *a, u16 *csum)
|
||||
{
|
||||
int rc;
|
||||
unsigned n;
|
||||
|
||||
n = *a++ << 8;
|
||||
n |= *a++;
|
||||
rc = iobuf_write(out, a, n );
|
||||
for( ; n; n--, a++ )
|
||||
*csum += *a;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Decode an external representation and return an MPI
|
||||
* Read an external representation of an mpi and return the MPI
|
||||
* The external format is a 16 bit unsigned value stored in network byte order,
|
||||
* giving the number of bits for the following integer. The integer is stored
|
||||
* with MSB first (left padded with zeroes to align on a byte boundary).
|
||||
*/
|
||||
MPI
|
||||
#ifdef M_DEBUG
|
||||
mpi_debug_decode(IOBUF inp, unsigned *ret_nread, const char *info)
|
||||
mpi_debug_read(IOBUF inp, unsigned *ret_nread, int secure, const char *info)
|
||||
#else
|
||||
mpi_decode(IOBUF inp, unsigned *ret_nread)
|
||||
mpi_read(IOBUF inp, unsigned *ret_nread, int secure)
|
||||
#endif
|
||||
{
|
||||
int c, i, j;
|
||||
@ -144,12 +107,15 @@ mpi_decode(IOBUF inp, unsigned *ret_nread)
|
||||
nbytes = (nbits+7) / 8;
|
||||
nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
|
||||
#ifdef M_DEBUG
|
||||
val = mpi_debug_alloc( nlimbs, info );
|
||||
val = secure? mpi_debug_alloc_secure( nlimbs, info )
|
||||
: mpi_debug_alloc( nlimbs, info );
|
||||
#else
|
||||
val = mpi_alloc( nlimbs );
|
||||
val = secure? mpi_alloc_secure( nlimbs )
|
||||
: mpi_alloc( nlimbs );
|
||||
#endif
|
||||
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
|
||||
i %= BYTES_PER_MPI_LIMB;
|
||||
val->nbits = nbits;
|
||||
j= val->nlimbs = nlimbs;
|
||||
val->sign = 0;
|
||||
for( ; j > 0; j-- ) {
|
||||
@ -171,103 +137,6 @@ mpi_decode(IOBUF inp, unsigned *ret_nread)
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Decode an MPI from the buffer, the buffer starts with two bytes giving
|
||||
* the length of the data to follow, the original data follows.
|
||||
* The MPI is alloced from secure MPI space
|
||||
*/
|
||||
MPI
|
||||
#ifdef M_DEBUG
|
||||
mpi_debug_decode_buffer(byte *buffer, const char *info )
|
||||
#else
|
||||
mpi_decode_buffer(byte *buffer )
|
||||
#endif
|
||||
{
|
||||
int i, j;
|
||||
u16 buflen;
|
||||
unsigned nbits, nbytes, nlimbs;
|
||||
mpi_limb_t a;
|
||||
byte *p = buffer;
|
||||
MPI val;
|
||||
|
||||
if( !buffer )
|
||||
log_bug("mpi_decode_buffer: no buffer\n");
|
||||
buflen = *p++ << 8;
|
||||
buflen |= *p++;
|
||||
nbits = *p++ << 8;
|
||||
nbits |= *p++;
|
||||
nbytes = (nbits+7) / 8;
|
||||
if( nbytes+2 != buflen )
|
||||
log_bug("mpi_decode_buffer: length conflict\n");
|
||||
nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
|
||||
#ifdef M_DEBUG
|
||||
val = mpi_debug_alloc_secure( nlimbs, info );
|
||||
#else
|
||||
val = mpi_alloc_secure( nlimbs );
|
||||
#endif
|
||||
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
|
||||
i %= BYTES_PER_MPI_LIMB;
|
||||
j= val->nlimbs = nlimbs;
|
||||
val->sign = 0;
|
||||
for( ; j > 0; j-- ) {
|
||||
a = 0;
|
||||
for(; i < BYTES_PER_MPI_LIMB; i++ ) {
|
||||
a <<= 8;
|
||||
a |= *p++;
|
||||
}
|
||||
i = 0;
|
||||
val->d[j-1] = a;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Read a MPI from the external medium and return it in a newly allocated
|
||||
* buffer (This buffer is allocated in the secure memory space, because
|
||||
* we properly need this to decipher this string).
|
||||
* Return: the allocated string and in RET_NREAD the number of bytes
|
||||
* read (including the 2 length bytes), the returned buffer will
|
||||
* be prefixed with two bytes describing the length of the following
|
||||
* data.
|
||||
*/
|
||||
byte *
|
||||
mpi_read(IOBUF inp, unsigned *ret_nread)
|
||||
{
|
||||
int c;
|
||||
u16 buflen;
|
||||
unsigned nbits, nbytes, nread;
|
||||
byte *p, *buf;
|
||||
|
||||
if( (c = iobuf_get(inp)) == -1 )
|
||||
return NULL;
|
||||
nbits = c << 8;
|
||||
if( (c = iobuf_get(inp)) == -1 )
|
||||
return NULL;
|
||||
nbits |= c;
|
||||
if( nbits > MAX_EXTERN_MPI_BITS ) {
|
||||
log_error("mpi too large (%u bits)\n", nbits);
|
||||
return NULL;
|
||||
}
|
||||
nread = 2;
|
||||
|
||||
nbytes = (nbits+7) / 8;
|
||||
buflen = nbytes + 2;
|
||||
p = buf = m_alloc_secure( buflen+2 );
|
||||
*p++ = buflen >> 8;
|
||||
*p++ = buflen & 0xff;
|
||||
*p++ = nbits >> 8;
|
||||
*p++ = nbits & 0xff;
|
||||
for( ; nbytes ; nbytes--, nread++ )
|
||||
*p++ = iobuf_get(inp) & 0xff;
|
||||
|
||||
if( nread > *ret_nread )
|
||||
log_error("Ooops: mpi crosses packet border");
|
||||
else
|
||||
*ret_nread = nread;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Make a mpi from a character string.
|
||||
@ -390,3 +259,96 @@ mpi_get_keyid( MPI a, u32 *keyid )
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Return a m_alloced buffer with the MPI (msb first).
|
||||
* NBYTES receives the length of this buffer. Caller must free the
|
||||
* return string (This function does return a 0 byte buffer with NBYTES
|
||||
* set to zero if the value of A is zero. If sign is not NULL, it will
|
||||
* be set to the sign of the A.
|
||||
*/
|
||||
byte *
|
||||
mpi_get_buffer( MPI a, unsigned *nbytes, int *sign )
|
||||
{
|
||||
byte *p, *buffer;
|
||||
mpi_limb_t alimb;
|
||||
int i;
|
||||
|
||||
if( sign )
|
||||
*sign = a->sign;
|
||||
*nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
|
||||
p = buffer = a->secure ? m_alloc_secure( *nbytes) : m_alloc( *nbytes );
|
||||
|
||||
for(i=a->nlimbs-1; i >= 0; i-- ) {
|
||||
alimb = a->d[i];
|
||||
#if BYTES_PER_MPI_LIMB == 4
|
||||
*p++ = alimb >> 24;
|
||||
*p++ = alimb >> 16;
|
||||
*p++ = alimb >> 8;
|
||||
*p++ = alimb ;
|
||||
#elif BYTES_PER_MPI_LIMB == 8
|
||||
*p++ = alimb >> 56;
|
||||
*p++ = alimb >> 48;
|
||||
*p++ = alimb >> 40;
|
||||
*p++ = alimb >> 32;
|
||||
*p++ = alimb >> 24;
|
||||
*p++ = alimb >> 16;
|
||||
*p++ = alimb >> 8;
|
||||
*p++ = alimb ;
|
||||
#else
|
||||
#error please implement for this limb size.
|
||||
#endif
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Use BUFFER to update MPI.
|
||||
*/
|
||||
void
|
||||
mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign )
|
||||
{
|
||||
const byte *p;
|
||||
mpi_limb_t alimb;
|
||||
int nlimbs;
|
||||
int i;
|
||||
|
||||
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
|
||||
RESIZE_IF_NEEDED(a, nlimbs);
|
||||
a->sign = sign;
|
||||
|
||||
for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) {
|
||||
#if BYTES_PER_MPI_LIMB == 4
|
||||
alimb = *p-- ;
|
||||
alimb |= *p-- << 8 ;
|
||||
alimb |= *p-- << 16 ;
|
||||
alimb |= *p-- << 24 ;
|
||||
#elif BYTES_PER_MPI_LIMB == 8
|
||||
#else
|
||||
#error please implement for this limb size.
|
||||
#endif
|
||||
a->d[i++] = alimb;
|
||||
}
|
||||
if( p >= buffer ) {
|
||||
#if BYTES_PER_MPI_LIMB == 4
|
||||
alimb = *p-- ;
|
||||
if( p >= buffer ) alimb |= *p-- << 8 ;
|
||||
if( p >= buffer ) alimb |= *p-- << 16 ;
|
||||
if( p >= buffer ) alimb |= *p-- << 24 ;
|
||||
#elif BYTES_PER_MPI_LIMB == 8
|
||||
alimb = *p-- ;
|
||||
if( p >= buffer ) alimb |= *p-- << 8 ;
|
||||
if( p >= buffer ) alimb |= *p-- << 16 ;
|
||||
if( p >= buffer ) alimb |= *p-- << 24 ;
|
||||
if( p >= buffer ) alimb |= *p-- << 32 ;
|
||||
if( p >= buffer ) alimb |= *p-- << 40 ;
|
||||
if( p >= buffer ) alimb |= *p-- << 48 ;
|
||||
if( p >= buffer ) alimb |= *p-- << 56 ;
|
||||
#else
|
||||
#error please implement for this limb size.
|
||||
#endif
|
||||
a->d[i++] = alimb;
|
||||
}
|
||||
a->nlimbs = i;
|
||||
assert( i == nlimbs );
|
||||
}
|
||||
|
||||
|
@ -456,3 +456,26 @@ m_is_secure( const void *p )
|
||||
return p && ((byte*)p)[-1] == MAGIC_SEC_BYTE;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Make a copy of the memory block at a
|
||||
*/
|
||||
void *
|
||||
FNAME(copy)( void *a FNAMEPRT )
|
||||
{
|
||||
void *b;
|
||||
size_t n;
|
||||
|
||||
if( !a )
|
||||
return a;
|
||||
|
||||
n = m_size(a);
|
||||
if( m_is_secure(a) )
|
||||
b = FNAME(alloc_secure)(n FNAMEARG);
|
||||
else
|
||||
b = FNAME(alloc)(n FNAMEARG);
|
||||
memcpy(b, a, n );
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user