x917.c
Go to the documentation of this file.
00001 00039 #include "x917.h" 00040 #include <sec/util.h> 00041 #include <drv/timer.h> 00042 #include "hw/hw_timer.h" 00043 00044 static void x917_next(X917Context *ctx, BlockCipher *cipher, uint8_t *out) 00045 { 00046 const size_t blen = cipher_block_len(cipher); 00047 00048 struct 00049 { 00050 time_t t0; 00051 hptime_t t1; 00052 uint8_t padding[blen - sizeof(time_t) - sizeof(hptime_t)]; 00053 } DT; 00054 00055 ASSERT(sizeof(DT) == blen); 00056 00057 memset(&DT, 0, sizeof(DT)); 00058 DT.t0 = timer_clock(); 00059 DT.t1 = timer_hw_hpread(); 00060 00061 cipher_ecb_encrypt(cipher, &DT); 00062 00063 xor_block(out, (uint8_t*)&DT, ctx->state, blen); 00064 cipher_ecb_encrypt(cipher, out); 00065 00066 xor_block(ctx->state, (uint8_t*)&DT, out, blen); 00067 cipher_ecb_encrypt(cipher, ctx->state); 00068 00069 PURGE(DT); 00070 } 00071 00072 00073 static void x917_generate(PRNG *ctx_, uint8_t *data, size_t len) 00074 { 00075 X917Context *ctx = (X917Context *)ctx_; 00076 BlockCipher *cipher = AES128_stackinit(); 00077 00078 const size_t blen = cipher_block_len(cipher); 00079 uint8_t temp[blen]; 00080 00081 ASSERT(len); 00082 ASSERT(sizeof(ctx->state) >= blen); 00083 ASSERT(sizeof(ctx->key) >= cipher_key_len(cipher)); 00084 00085 cipher_set_key(cipher, ctx->key); 00086 00087 while (len) 00088 { 00089 size_t L = MIN(blen, len); 00090 x917_next(ctx, cipher, temp); 00091 memcpy(data, temp, L); 00092 len -= L; 00093 data += L; 00094 } 00095 } 00096 00097 static void x917_reseed(PRNG *ctx_, const uint8_t *seed) 00098 { 00099 // The X9.17 standard does not specify reseeding. To avoid external 00100 // dependencies, we implement it this way: 00101 // * Generate a new random block, xor it with the first part 00102 // of the seed, and use the result as new seed. 00103 // * Generate and throw away a block to update the state. 00104 X917Context *ctx = (X917Context *)ctx_; 00105 const size_t klen = sizeof(ctx->key); 00106 const size_t blen = sizeof(ctx->state); 00107 00108 if (!ctx->rng.seeded) 00109 { 00110 memcpy(ctx->key, seed, klen); 00111 memcpy(ctx->state, seed+klen, blen); 00112 } 00113 else 00114 { 00115 uint8_t buf[klen]; 00116 x917_generate(ctx_, buf, klen); 00117 00118 xor_block(ctx->key, buf, seed, klen); 00119 xor_block(ctx->state, ctx->state, seed+klen, blen); 00120 00121 PURGE(buf); 00122 } 00123 } 00124 00125 /*********************************************************************/ 00126 00127 void x917_init(X917Context *ctx) 00128 { 00129 ctx->rng.reseed = x917_reseed; 00130 ctx->rng.generate = x917_generate; 00131 ctx->rng.seed_len = sizeof(ctx->key) + sizeof(ctx->state); 00132 ctx->rng.seeded = 0; 00133 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)