Data Signing, Encryption, and Hash Functions
v3HashInitSyntax#include "security.h" s32 v3HashInit( v3_HASH_TMP * tmp, u32 hash_type ); DescriptionInitialize the temporary structure tmp and setup to perform the data hashing. See lib/security.* for examples of how to add a new hash algorithms. If you add an algorithm, you should also add a define similar to V3_HASH_SHA1 for users. Predefined Hash Types
Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplev3_HASH_TMP work; v3MemSet( &work, v3u64u32( sizeof( v3_HASH_TMP ) ), 0 ); if ( v3HashInit( &work, V3_HASH_MD5 ) != V3_PASS ) { /* Failed */ return( V3_FAIL ); } v3HashSyntax#include "security.h" s32 v3Hash( v3_HASH_TMP * tmp, const u8 * const data, u64 length ); DescriptionFeed length bytes of data into the work hash. Make sure your data has been v3Save'd before using this. Return ValuesV3_PASS on success, or an error code on failure. Errors
Exampleascii string[2388] = V3_TEST_TEXT_BLOCK; v3_HASH_TMP work; /* v3HashInit() ... */ if ( v3Hash( &work, (ascii *) &string, v3u64u32( sizeof( string ) ) ) != V3_PASS ) { /* Failed */ return( V3_FAIL ); } v3HashEndSyntax#include "security.h" s32 v3HashEnd( v3_HASH * hash, v3_HASH_TMP * tmp ); DescriptionTake the work data and generate the final hash. Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplev3_HASH_TMP work; v3_HASH hash; /* v3HashInit() and v3Hash() ... */ if ( v3HashEnd( &hash, &work ) != V3_PASS ) { /* Failed */ return( V3_FAIL ); } v3HashEqSyntax#include "security.h" s32 v3HashEq( const v3_HASH * hashA, const v3_HASH * hashB ); DescriptionCheck if the hashes are equal. Return Values1 if the hashes are equal, or 0 if they are not equal. ErrorsNone. Examplev3_HASH hashA, hashB; /* Fill in the hashes ... */ if( !v3HashEq( &hashA, &hashB ) ) { /* Hashes are not equal */ } v3PRNGSyntax#include "security.h" s32 v3PRNG( v3_PRNG * prng, void * data, u64 length, const void * salt, u64 salt_length ); DescriptionGenerate length bytes of deterministic psuedo-random data. Initialization of the generator is done by feeding it salt_length bytes of salt. Any salt fed to the generator will be used before the data is generated, and is also cumulative, so it can be called repeatedly with additional salt to provide more initial randomness. Given the same salt, the same bytes will always come out. Return ValuesV3_PASS on success, or V3_FAIL on failure. ErrorsNone. Examplev3_PRNG rnd; u8 bytes[32]; v3_time mytime; v3MemSet( &rnd, v3u64u32( sizeof( v3_PRNG ) ), 0 ); /* seed it */ v3PRNG( &rnd, NULL, v3u64u32( 0 ), &mytime, v3u64u32( sizeof( v3_time ) ) ); /* get some bytes */ v3PRNG( &rnd, bytes, v3u64u32( sizeof( bytes ) ), NULL, v3u64u32( 0 ) ); /* OR - do both at once */ v3PRNG( &rnd, bytes, v3u64u32( sizeof( bytes ) ), &mytime, v3u64u32( sizeof( v3_time ) ) ); v3EncryptInitSyntax#include "security.h" s32 v3EncryptInit( v3_BUFFER * output, v3_ENCODER_TMP * tmp, u32 encryption_type, u32 direction, u32 mode, const u8 * key, u32 key_bits, const u8 * iv ); DescriptionInitializes the output buffer and sets up the temporary data structure tmp needed to perform the type of encryption requested. direction must be either V3_ENCODER_ENCODE (encrypt) or V3_ENCODER_DECODE (decrypt). mode must be one of the modes listed below. All algorithms will use a 128bit block size, and so ECB and CBC modes will always output a multiple of 16 bytes. key should point to key_bits worth of key data. CBC and CFB modes need 16 bytes of iv. Those who need to add additional encryption types should see Encoder Functions as the encryption functions are actually an interface to the encoder functions. Knowing what you're doing before using encryption functions would be a very good idea. Do not call v3BufferCreate on output yourself - you still need to v3BufferFree it after you're done with it of course. Predefined Encryption Types:
Encryption Modes:
Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplev3_BUFFER buf; v3_ENCODER_TMP tmp; v3_HASH hash; v3MemSet( &buf, v3u64u32( sizeof( v3_BUFFER ) ), 0 ); v3MemSet( &tmp, v3u64u32( sizeof( v3_ENCODER_TMP ) ), 0 ); /* ... setup hash ... and IV if you have one */ /* Init encryption */ if ( v3EncryptInit( &buf, &tmp, V3_CRYPTO_AES, V3_ENCODER_ENCODE, V3_CRYPTO_MODE_ECB, &hash, 128, NULL ) != V3_PASS ) { return( -1 ); } v3EncryptSyntax#include "security.h" s32 v3Encrypt( v3_BUFFER * output, v3_ENCODER_TMP * tmp, const void * const data, u64 length ); DescriptionFeed length bytes of data into the encryption routines. Any encrypted data will be placed into the output buffer but may not be put into the output buffer after every call for some algorithms. ECB and CBC modes will always output multiples of 16 bytes. Make sure your data has been v3Save'd before using this. Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplev3_BUFFER buf; v3_ENCODER_TMP tmp; u8 data[8] = { 0, 1, 2, 3, 3, 3, 3, 4 }; u32 i; /* ... */ for ( i = 0 ; i < 100 ; i++ ) { if ( v3Encrypt( &buf, &tmp, data, v3u64u32( 8 ) ) != V3_PASS ) { return( -2 ); } } v3EncryptEndSyntax#include "security.h" s32 v3EncryptEnd( v3_BUFFER * output, v3_ENCODER_TMP * tmp ); DescriptionClear any temporary data and put the last of the encrypted data into the buffer. Make sure to empty and v3BufferFree the output buffer of your data after calling this function. If this function fails, you must call it again. This second call will always succeed and clean up any mess. Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplev3_BUFFER buf; v3_ENCODER_TMP tmp; /* ... */ if ( v3EncryptEnd( &buf, &tmp ) != V3_PASS ) { /* v3EncryptEnd() must be called again on an error */ v3EncryptEnd( &tmp ); return( -3 ); } /* empty out the buffer */ /* then dont forget to free it */ v3BufferFree( &buf ); v3PKIKeyGenSyntax#include "security.h" s32 v3PKIKeyGen( v3_PKI_KEY * public_key, v3_PKI_KEY * private_key, u32 bits, const u8 * rnd_bits, u64 user_id, const ascii * alias, v3_time create, v3_time expire, void (*callback)( s32, s32, void * ), void * callback_param ); DescriptionGenerate public_key and private_key with a bits bit n. Please read this entire description, as many parameters have special meanings and restrictions. Knowing what you're doing before using any PKI functions would be a very good idea. bits must be at least 512, and a power of 2. Keys of 1024 bits are now suspected to be breakable by large organizations and governments, and 512 bit keys are breakable with a few computers in a few weeks, so 2048 is the smallest key recommended. rnd_bits should be bits bits of random data. It is VERY important that the user take great care to make sure that these bits are truely random, and not based on any data such as the time. v3PRNG and v3Entropy are also not enough on their own. create is the time of key creation and should always be the current time. expire is the expiration time of the keys. v3PKIEncode will not be allowed with an expired key. Most keys should have a lifetime of 1 year.
The user_id on a key has specific ranges and meanings: A key is uniquely identified by the bits, user_id, and create. This means that keys should not be generated more then once a second, this should not be a big concern. You should also never generate a key with a user_id you haven't been assigned, because it will not result in a valid key. alias is a max 15 character ascii string that has no special meaning except to the key's owner as a tool to quickly tell keys apart. No special meaning should be given beyond that. callback and callback_param provide information on the possibly long key generation process. They work as decribed in v3BNPrimeGen, with the added calls of callback( 3, 0, callback_param ) when the keypair test begins and callback( 4, 0, callback_param ) when the test finishes. Note that 2 primes will be generated during key creation. The user-relevant (only) elements of v3_PKI_KEY are: typedef struct { u16 pkt_type; /* == V3_PKI_PUBLIC or V3_PKI_PRIVATE */ u16 pkt_version; u32 bits; s64 create; u64 user_id; s64 expire; ascii alias[16]; ... } v3_PKI_KEY; Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplevoid my_progress( s32 type, s32 count, void * param ) { switch( type ) { case 0: v3PrintA( "." ); break; case 1: v3PrintA( "+" ); break; case 2: v3PrintA( "\n" ); break; case 3: v3PrintA( "[testing keypair..." ); break; case 4: v3PrintA( "]\n" ); break; default: break; } } void example( void ) { const ascii alias[16]; v3_PKI_KEY pub, pri; v3_time create, expire; u8 rnd_bits[256]; /* set create, and expire in a year */ v3SystemClock( &create ); _V3_SET128( expire, 00000000, 01E13380, 00000000, 00000000 ); expire = v3s128Add( create, expire ); /* get user data and carefully construct rnd_bits */ /* set alias to make a key for at work, employee id = 42 */ v3StrCopyA( alias, (ascii *) "Salt mines 2002", v3u64u32( 16 ) ); /* generate a key */ v3MemSet( &pub, v3u64u32( sizeof( v3_PKI_KEY ) ), 0 ); v3MemSet( &pri, v3u64u32( sizeof( v3_PKI_KEY ) ), 0 ); if ( v3PKIKeyGen( &pub, &pri, 2048, rnd_bits, v3u64u32( 42 ), alias, create, expire, my_progress, NULL ) != V3_PASS ) { /* key generation failed */ } /* save the keys, or use them as ephemeral keys */ /* ... */ } v3PKIKeyLoadSyntax#include "security.h" s32 v3PKIKeyLoad( v3_PKI_KEY * key, u64 * bytes_read, const u8 * buffer, u64 max_bytes, const v3_HASH * pass_hash ); DescriptionLoad the key from the buffer into key, reading at most max_bytes bytes. bytes_read will be set to the number of bytes that were in the key. Loading private keys also requires the V3_HASH_MD5SHA1 hash of the users passphrase pass_hash in order to decrypt the private data. When loading a public key pass_hash is ignored. Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplev3_PKI_KEY pub, pri; v3_HASH pass_hash; u8 save_buf[4096]; u64 len; /* read key from file etc. */ /* loading a public key */ if ( v3PKIKeyLoad( &pub, &len, save_buf, v3u64u32( sizeof( save_buf ) ), NULL ) != V3_PASS ) { /* Load failed */ } /* hash passphrase into pass_hash with V3_HASH_MD5SHA1 */ /* loading a private key */ if ( v3PKIKeyLoad( &pri, &len, save_buf, v3u64u32( sizeof( save_buf ) ), &data_hash ) != V3_PASS ) { /* Load failed */ } /* free keys */ v3PKIKeyFree( &pub ); v3PKIKeyFree( &pri ); v3PKIKeySaveSyntax#include "security.h" s32 v3PKIKeySave( u8 * buffer, u64 * length, const v3_PKI_KEY * key, const u64 max_bytes, const u8 * rnd_bytes, const v3_HASH * pass_hash ); DescriptionSave the key key into the buffer, writing at most max_bytes bytes. length will be set to the number of bytes written. Private keys also requite 16 bytes of random data rnd_bytes, and a hash pass_hash which is the V3_HASH_MD5SHA1 hash of the users passphrase in order to encrypt the private data. When saving a public key these two parameters are ignored. Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplev3_PKI_KEY pub, pri; v3_HASH pass_hash; u8 save_buf[4096]; u64 len; /* generate a keypair - if we load keys we dont need to re-save them */ /* saving a public key */ if ( v3PKIKeySave( save_buf, &len, &pub, v3u64u32( sizeof( save_buf ) ), NULL, NULL ) != V3_PASS ) { /* Save failed */ } /* write save_buf to file etc. */ /* generate 16 random bytes for the rnd_bytes */ /* hash passphrase into pass_hash with V3_HASH_MD5SHA1 */ /* saving a private key */ if ( v3PKIKeySave( save_buf, &len, &pri, v3u64u32( sizeof( save_buf ) ), rnd_bits, &pass_hash ) != V3_PASS ) { /* Save failed */ } /* write save_buf to file etc. */ /* free keys */ v3PKIKeyFree( &pub ); v3PKIKeyFree( &pri ); v3PKIKeyFreeSyntax#include "security.h" void v3PKIKeyFree( v3_PKI_KEY * key ); DescriptionFree all internal key data, and zero the key structure. Return ValuesNone. ErrorsNone. Examplev3_PKI_KEY key; v3MemSet( &key, v3u64u32( sizeof( v3_PKI_KEY ) ), 0 ); /* use the key */ v3PKIKeyFree( &key ); v3PKISigLoadSyntax#include "security.h" s32 v3PKISigLoad( v3_PKI_SIG * sig, u64 * bytes_read, const u8 * buffer, u64 max_bytes ); DescriptionLoad the signature from the buffer into sig, reading at most max_bytes bytes. bytes_read will be set to the number of bytes that were in the signature. Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplev3_PKI_SIG sig; u8 save_buf[4096]; u64 len; if ( v3PKISigLoad( &sig, &len, save_buf, v3u64u32( 4096 ) ) != V3_PASS ) { /* failure to read signature */ } /* use signature for key or verification */ /* free signature */ v3PKISigFree( &sig ); v3PKISigSaveSyntax#include "security.h" s32 v3PKISigSave( u8 * buffer, u64 * length, const v3_PKI_SIG * sig, u64 max_bytes ); DescriptionSave the signature sig into the buffer, writing at most max_bytes bytes. length will be set to the number of bytes written. Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplev3_PKI_SIG sig; u8 save_buf[4096]; u64 len; /* load or create signature */ if ( v3PKISigSave( save_buf, &len, &sig, v3u64u32( 4096 ) ) != V3_PASS ) { /* failure to write signature */ } /* free signature */ v3PKISigFree( &sig ); v3PKISigFreeSyntax#include "security.h" void v3PKISigFree( v3_PKI_SIG * sig ); DescriptionFree all internal data, and zero the signature structure. Return ValuesV3_PASS on success, or an error code on failure. ErrorsNone. Examplev3_PKI_SIG sig; v3MemSet( &sig, v3u64u32( sizeof( v3_PKI_SIG ) ), 0 ); /* use the sig */ v3PKISigFree( &sig ); v3PKIEncodeSyntax#include "security.h" s32 v3PKIEncode( v3_PKI_SIG * sig, const v3_HASH * hash, v3_time timestamp, u8 type, u8 shared, const v3_PKI_KEY * key ); DescriptionUse the key to encode the hash data, timestamp (in seconds), type, and shared flag into the signature sig. A signature of type V3_PKI_SIG_MESSAGE needs a public key, all other types need a private key to encode. You should always use V3_HASH_MD5SHA1 to generate the hash for signatures. Care should be taken in chosing the type and shared flag you use. The user-relevant (only) elements of v3_PKI_SIG are: typedef struct { u16 pkt_type; /* == V3_PKI_SIG */ u16 pkt_version; u32 bits; s64 create; u64 user_id; s64 timestamp; u8 type; u8 shared; v3_BN sig; } v3_PKI_SIG; Signature Types
Shared Flags
Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplev3_HASH data_hash, sig_hash; v3_PKI_KEY pri; v3_PKI_SIG sig; v3_time sig_time; u8 sig_type; u8 share; /* hash the data into data_hash (use V3_HASH_MD5SHA1) */ /* load private key into pub with v3PKIKeyLoad() */ /* get the current time */ v3SystemClock( &time_now ); /* Sign the hash */ if ( v3PKIEncode( &sig, &data_hash, time_now, V3_PKI_SIG_SIGN, V3_PKI_SHARED_YES, &pri ) != V3_PASS ) { /* Encoding failed */ } /* save the signature with v3PKISigSave() */ /* free the key and sig */ v3PKIKeyFree( &key ); v3PKISigFree( &sig ); v3PKIDecodeSyntax#include "security.h" s32 v3PKIDecode( v3_HASH * hash, v3_time * timestamp, u8 * type, u8 * shared, const v3_PKI_SIG * sig, const v3_PKI_KEY * key ); DescriptionExtract the hash, timestamp, type, and shared flag from the signature sig using the key. A V3_PASS from this function does NOT mean the signature is valid, only that it was decoded correctly. A signature of type V3_PKI_SIG_MESSAGE needs a private key, all other types need a public key to decode. It is important to understand that the undecoded parameters of a signature (sig.timestamp, sig.type, sig.shared) are MEANINGLESS, because they can be trivially modified by an attacker. Only use the decoded values. Signature Types
Shared Flags
Return ValuesV3_PASS on success, or an error code on failure. Errors
Examplev3_HASH data_hash, sig_hash; v3_PKI_KEY pub; v3_PKI_SIG sig; v3_time sig_time; u8 sig_type; u8 share; /* hash the data into data_hash (use V3_HASH_MD5SHA1) */ /* load public key into pub with v3PKIKeyLoad() */ /* load the signature into sig with v3PKISigLoad() */ if ( v3PKIDecode( &sig_hash, &sig_time, &sig_type, &share, &sig, &pub ) != V3_PASS ) { /* decode failed */ } /* now verify the signature */ if ( !v3HashEq( &data_hash, &sig_hash ) ) { /* Signature was not for the data we hashed */ } /* sig_time, sig_type, and share are now what the signer set them to, and effect what it means. */ v3PKIKeyFree( &key ); v3PKISigFree( &sig );
© Copyright Mithral Communications & Design Inc.
1995-2003.
All rights reserved.
Mithral® and Cosm® are trademarks of
Mithral Communications & Design Inc.
|