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