[OpenPGP:SDK svn] r343 - in openpgpsdk/trunk: examples include/openpgpsdk src

Subversion ben at algroup.co.uk
Mon Jan 30 16:10:44 GMT 2006


Author: ben
Date: 2006-01-30 16:10:43 +0000 (Mon, 30 Jan 2006)
New Revision: 343

Modified:
   openpgpsdk/trunk/examples/packet-dump.c
   openpgpsdk/trunk/include/openpgpsdk/crypto.h
   openpgpsdk/trunk/include/openpgpsdk/packet.h
   openpgpsdk/trunk/src/packet-parse.c
   openpgpsdk/trunk/src/signature.c
   openpgpsdk/trunk/src/symmetric.c
Log:
Working secret key decryption!


Modified: openpgpsdk/trunk/examples/packet-dump.c
===================================================================
--- openpgpsdk/trunk/examples/packet-dump.c	2006-01-30 13:36:42 UTC (rev 342)
+++ openpgpsdk/trunk/examples/packet-dump.c	2006-01-30 16:10:43 UTC (rev 343)
@@ -830,7 +830,7 @@
 	printf("Hash algorithm: %d\n",content->secret_key.hash_algorithm);
 	print_hexdump("Salt",content->secret_key.salt,
 		      sizeof content->secret_key.salt);
-	printf("Iterations: %d\n",content->secret_key.iterations);
+	printf("Octet count: %d\n",content->secret_key.octet_count);
 	print_hexdump("IV",content->secret_key.iv,
 		      ops_block_size(content->secret_key.algorithm));
 
@@ -838,8 +838,6 @@
 	if(content_->tag == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY)
 	    break;
 
-	printf("Checksum: %04x\n",content->secret_key.checksum);
-
 	switch(content->secret_key.public_key.algorithm)
 	    {
 	case OPS_PKA_RSA:
@@ -856,6 +854,13 @@
 	default:
 	    assert(0);
 	    }
+
+	if(content->secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED)
+	    print_hexdump("Checkhash",content->secret_key.checkhash,
+			  OPS_CHECKHASH_SIZE);
+	else
+	    printf("Checksum: %04x\n",content->secret_key.checksum);
+
 	break;
 
     case OPS_PTAG_CT_ARMOUR_HEADER:

Modified: openpgpsdk/trunk/include/openpgpsdk/crypto.h
===================================================================
--- openpgpsdk/trunk/include/openpgpsdk/crypto.h	2006-01-30 13:36:42 UTC (rev 342)
+++ openpgpsdk/trunk/include/openpgpsdk/crypto.h	2006-01-30 16:10:43 UTC (rev 343)
@@ -8,7 +8,8 @@
 #include "packet.h"
 #include "packet-parse.h"
 
-#define OPS_MAX_HASH	64
+#define OPS_MAX_HASH_SIZE	64
+#define OPS_MIN_HASH_SIZE	16
 
 typedef void ops_hash_init_t(ops_hash_t *hash);
 typedef void ops_hash_add_t(ops_hash_t *hash,const unsigned char *data,
@@ -75,6 +76,7 @@
 			    const ops_rsa_public_key_t *rsa);
 
 unsigned ops_block_size(ops_symmetric_algorithm_t alg);
+unsigned ops_key_size(ops_symmetric_algorithm_t alg);
 
 int ops_decrypt_data(ops_region_t *region,ops_parse_info_t *parse_info);
 

Modified: openpgpsdk/trunk/include/openpgpsdk/packet.h
===================================================================
--- openpgpsdk/trunk/include/openpgpsdk/packet.h	2006-01-30 13:36:42 UTC (rev 342)
+++ openpgpsdk/trunk/include/openpgpsdk/packet.h	2006-01-30 16:10:43 UTC (rev 343)
@@ -421,6 +421,9 @@
 // Salt size for hashing
 #define OPS_SALT_SIZE		8
 
+// Hash size for secret key check
+#define OPS_CHECKHASH_SIZE	20
+
 /** ops_secret_key_t
  */
 typedef struct
@@ -431,10 +434,11 @@
     ops_symmetric_algorithm_t	algorithm;
     ops_hash_algorithm_t	hash_algorithm;
     unsigned char		salt[OPS_SALT_SIZE];
-    unsigned			iterations;
+    unsigned			octet_count;
     unsigned char		iv[OPS_MAX_BLOCK_SIZE];
+    ops_secret_key_union_t	key;
     unsigned			checksum;
-    ops_secret_key_union_t	key;
+    unsigned char		checkhash[OPS_CHECKHASH_SIZE];
     } ops_secret_key_t;
 
 /** Structure to hold one trust packet's data */

Modified: openpgpsdk/trunk/src/packet-parse.c
===================================================================
--- openpgpsdk/trunk/src/packet-parse.c	2006-01-30 13:36:42 UTC (rev 342)
+++ openpgpsdk/trunk/src/packet-parse.c	2006-01-30 16:10:43 UTC (rev 343)
@@ -1792,6 +1792,7 @@
     int ret=1;
     ops_region_t encregion;
     ops_region_t *saved_region=NULL;
+    size_t checksum_length=2;
 
     memset(&content,'\0',sizeof content);
     if(!parse_public_key_data(&C.secret_key.public_key,region,parse_info))
@@ -1800,6 +1801,9 @@
 	return 0;
     C.secret_key.s2k_usage=c[0];
 
+    if(C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED)
+	checksum_length=20;
+
     if(C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED
        || C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED)
 	{
@@ -1827,7 +1831,7 @@
 	    {
 	    if(!limited_read(c,1,region,parse_info))
 		return 0;
-	    C.secret_key.iterations=(16+(c[0]&15)) << ((c[0] >> 4)+6);
+	    C.secret_key.octet_count=(16+(c[0]&15)) << ((c[0] >> 4)+6);
 	    }
 	}
     else if(C.secret_key.s2k_usage != OPS_S2KU_NONE)
@@ -1845,7 +1849,11 @@
 	int n;
 	ops_parser_content_t pc;
 	char *passphrase;
-	unsigned char hash[OPS_MAX_HASH];
+	unsigned char key[OPS_MAX_KEY_SIZE+OPS_MAX_HASH_SIZE];
+	ops_hash_t hashes[(OPS_MAX_KEY_SIZE+OPS_MIN_HASH_SIZE-1)/OPS_MIN_HASH_SIZE];
+	int keysize;
+	int hashsize;
+	size_t l;
 
 	n=ops_block_size(C.secret_key.algorithm);
 	assert(n > 0 && n <= OPS_MAX_BLOCK_SIZE);
@@ -1866,17 +1874,75 @@
 	    return 1;
 	    }
 
-	ops_hash(hash,C.secret_key.hash_algorithm,passphrase,
-		 strlen(passphrase));
+	keysize=ops_key_size(C.secret_key.algorithm);
+	assert(keysize > 0 && keysize <= OPS_MAX_KEY_SIZE);
 
+	hashsize=ops_hash_size(C.secret_key.hash_algorithm);
+	assert(hashsize > 0 && hashsize <= OPS_MAX_HASH_SIZE);
+
+	for(n=0 ; n*hashsize < keysize ; ++n)
+	    {
+	    int i;
+
+	    ops_hash_any(&hashes[n],C.secret_key.hash_algorithm);
+	    hashes[n].init(&hashes[n]);
+	    // preload hashes with zeroes...
+	    for(i=0 ; i < n ; ++i)
+		hashes[n].add(&hashes[n],"",1);
+	    }
+
+	l=strlen(passphrase);
+
+	for(n=0 ; n*hashsize < keysize ; ++n)
+	    {
+	    unsigned i;
+
+	    switch(C.secret_key.s2k_specifier)
+		{
+	    case OPS_S2KS_SALTED:
+		hashes[n].add(&hashes[n],C.secret_key.salt,OPS_SALT_SIZE);
+		// flow through...
+	    case OPS_S2KS_SIMPLE:
+		hashes[n].add(&hashes[n],passphrase,l);
+		break;
+
+	    case OPS_S2KS_ITERATED_AND_SALTED:
+		for(i=0 ; i < C.secret_key.octet_count ; i+=l+OPS_SALT_SIZE)
+		    {
+		    int j=l+OPS_SALT_SIZE;
+
+		    if(i+j > C.secret_key.octet_count && i != 0)
+			j=C.secret_key.octet_count-i;
+
+		    hashes[n].add(&hashes[n],C.secret_key.salt,
+				  j > OPS_SALT_SIZE ? OPS_SALT_SIZE : j);
+		    if(j > OPS_SALT_SIZE)
+			hashes[n].add(&hashes[n],passphrase,j-OPS_SALT_SIZE);
+		    }
+			
+		}
+	    }
+
+	for(n=0 ; n*hashsize < keysize ; ++n)
+	    {
+	    int r=hashes[n].finish(&hashes[n],key+n*hashsize);
+	    assert(r == hashsize);
+	    }
+
 	ops_decrypt_any(&decrypt,C.secret_key.algorithm);
 	decrypt.set_iv(&decrypt,C.secret_key.iv);
-	decrypt.set_key(&decrypt,hash);
+	decrypt.set_key(&decrypt,key);
 
+	/* We need to prevent the decrypter from reading the trailing
+	   checksum */
+	region->length-=checksum_length;
 	ops_reader_push_decrypt(parse_info,&decrypt,region);
 
-	/* Since all known encryption for PGP doesn't compress, we can limit
-	   to the same length as the current region (for now) */
+	/* Since all known encryption for PGP doesn't compress, we can
+	   limit to the same length as the current region (for now),
+	   allowing for the trailing checksum.
+	*/
+
 	ops_init_subregion(&encregion,NULL);
 	encregion.length=region->length-region->length_read;
 	saved_region=region;
@@ -1911,16 +1977,28 @@
     if(saved_region)
 	{
 	ops_reader_pop_decrypt(parse_info);
+	assert(region->length_read == region->length);
 	region=saved_region;
+	/* put back checksum data */
+	region->length+=checksum_length;
 	}
 
     if(!ret)
 	return 0;
 
-    if(!limited_read_scalar(&C.secret_key.checksum,2,region,parse_info))
-	return 0;
     // XXX: check the checksum
 
+    if(C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED)
+	{
+	if(!limited_read(C.secret_key.checkhash,20,region,parse_info))
+	    return 0;
+	}
+    else
+	{
+	if(!limited_read_scalar(&C.secret_key.checksum,2,region,parse_info))
+	    return 0;
+	}
+
     CBP(parse_info,OPS_PTAG_CT_SECRET_KEY,&content);
 
     return 1;

Modified: openpgpsdk/trunk/src/signature.c
===================================================================
--- openpgpsdk/trunk/src/signature.c	2006-01-30 13:36:42 UTC (rev 342)
+++ openpgpsdk/trunk/src/signature.c	2006-01-30 16:10:43 UTC (rev 343)
@@ -217,7 +217,7 @@
 					      const ops_public_key_t *signer)
     {
     int n;
-    unsigned char hashout[OPS_MAX_HASH];
+    unsigned char hashout[OPS_MAX_HASH_SIZE];
 
     n=hash->finish(hash,hashout);
 

Modified: openpgpsdk/trunk/src/symmetric.c
===================================================================
--- openpgpsdk/trunk/src/symmetric.c	2006-01-30 13:36:42 UTC (rev 342)
+++ openpgpsdk/trunk/src/symmetric.c	2006-01-30 16:10:43 UTC (rev 343)
@@ -3,34 +3,11 @@
 #include <assert.h>
 #include <openssl/cast.h>
 
-unsigned ops_block_size(ops_symmetric_algorithm_t alg)
-    {
-    // perhaps do this via the underlying algorithm later
-    switch(alg)
-	{
-    case OPS_SA_PLAINTEXT:
-	return 1;
-
-    case OPS_SA_IDEA:
-    case OPS_SA_TRIPLEDES:
-    case OPS_SA_CAST5:
-    case OPS_SA_BLOWFISH:
-    case OPS_SA_TWOFISH:
-	return 8;
-
-    case OPS_SA_AES_128:
-    case OPS_SA_AES_192:
-    case OPS_SA_AES_256:
-	return 16;
-	}
-
-    return 0;
-    }
-
 typedef struct
     {
     unsigned char decrypted[1024];
     size_t decrypted_count;
+    size_t decrypted_offset;
     ops_decrypt_t *decrypt;
     ops_region_t *region;
     } encrypted_arg_t;
@@ -58,8 +35,9 @@
 	    else
 		n=length;
 
-	    memcpy(dest,arg->decrypted,n);
+	    memcpy(dest,arg->decrypted+arg->decrypted_offset,n);
 	    arg->decrypted_count-=n;
+	    arg->decrypted_offset+=n;
 	    length-=n;
 	    dest+=n;
 	    }
@@ -88,6 +66,8 @@
 						       arg->decrypted,
 						       buffer,n);
 	    assert(arg->decrypted_count > 0);
+
+	    arg->decrypted_offset=0;
 	    }
 	}
 
@@ -173,16 +153,39 @@
     TRAILER
     };
 
-void ops_decrypt_any(ops_decrypt_t *decrypt,ops_symmetric_algorithm_t alg)
+static ops_decrypt_t *get_proto(ops_symmetric_algorithm_t alg)
     {
     switch(alg)
 	{
     case OPS_SA_CAST5:
-	*decrypt=cast5;
-	break;
+	return &cast5;
 
     default:
 	assert(0);
 	}
+
+    return NULL;
     }
 
+void ops_decrypt_any(ops_decrypt_t *decrypt,ops_symmetric_algorithm_t alg)
+    { *decrypt=*get_proto(alg); }
+
+unsigned ops_block_size(ops_symmetric_algorithm_t alg)
+    {
+    ops_decrypt_t *p=get_proto(alg);
+
+    if(!p)
+	return 0;
+
+    return p->blocksize;
+    }
+
+unsigned ops_key_size(ops_symmetric_algorithm_t alg)
+    {
+    ops_decrypt_t *p=get_proto(alg);
+
+    if(!p)
+	return 0;
+
+    return p->keysize;
+    }



More information about the OpenPGPsdk-svn mailing list