diff options
Diffstat (limited to 'src/key_derivation.c')
-rw-r--r-- | src/key_derivation.c | 116 |
1 files changed, 76 insertions, 40 deletions
diff --git a/src/key_derivation.c b/src/key_derivation.c index 2911272..070cade 100644 --- a/src/key_derivation.c +++ b/src/key_derivation.c @@ -65,7 +65,7 @@ int key_derivation_init(key_derivation_t* kd, const char* type, int8_t ld_kdr, u kd->ld_kdr_ = sizeof(seq_nr_t) * 8; kd->key_length_ = key_len * sizeof(key[0]) * 8; - kd->handle_ = 0; + kd->params_ = NULL; int i; for(i = 0; i<KD_LABEL_COUNT; ++i) { @@ -178,14 +178,35 @@ int key_derivation_aesctr_init(key_derivation_t* kd) return -1; } } + + if(kd->params_) + free(kd->params_); + kd->params_ = malloc(sizeof(key_derivation_aesctr_param_t)); + if(!kd->params_) + return -2; + + key_derivation_aesctr_param_t* params = kd->params_; + +#ifndef NO_LIBGMP + mpz_init2(params->mp_ctr, 128); + mpz_init2(params->mp_key_id, 128); +#endif - gcry_error_t err = gcry_cipher_open(&kd->handle_, algo, GCRY_CIPHER_MODE_CTR, 0); + params->ctr_.length_ = 16; + params->ctr_.buf_ = malloc(params->ctr_.length_); + if(!params->ctr_.buf_) { + free(kd->params_); + kd->params_ = NULL; + return -2; + } + + gcry_error_t err = gcry_cipher_open(¶ms->handle_, algo, GCRY_CIPHER_MODE_CTR, 0); if(err) { log_printf(ERR, "failed to open key derivation cipher: %s/%s", gcry_strerror(err), gcry_strsource(err)); return -1; } - err = gcry_cipher_setkey(kd->handle_, kd->master_key_.buf_, kd->master_key_.length_); + err = gcry_cipher_setkey(params->handle_, kd->master_key_.buf_, kd->master_key_.length_); if(err) { log_printf(ERR, "failed to set key derivation key: %s/%s", gcry_strerror(err), gcry_strsource(err)); return -1; @@ -199,24 +220,40 @@ void key_derivation_aesctr_close(key_derivation_t* kd) if(!kd) return; - if(kd->handle_) - gcry_cipher_close(kd->handle_); + if(kd->params_) { + key_derivation_aesctr_param_t* params = kd->params_; +#ifndef NO_LIBGMP + mpz_clear(params->mp_ctr); + mpz_clear(params->mp_key_id); +#endif + if(params->ctr_.buf_) + free(params->ctr_.buf_); + + if(params->handle_) + gcry_cipher_close(params->handle_); + + free(kd->params_); + } } -int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, key_store_t* result, satp_prf_label_t label, seq_nr_t seq_nr) +int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, seq_nr_t* r, satp_prf_label_t label, seq_nr_t seq_nr) { - if(!kd || !result) + if(!kd || !kd->params_ || !r) + return -1; + + key_derivation_aesctr_param_t* params = kd->params_; + if(!params->ctr_.buf_) return -1; + - seq_nr_t r = 0; + *r = 0; if(kd->ld_kdr_ >= 0) - r = seq_nr >> kd->ld_kdr_; + *r = seq_nr >> kd->ld_kdr_; - if(kd->key_store_[label].key_.buf_ && kd->key_store_[label].r_ == r) { - if(!r || (seq_nr % r)) + if(kd->key_store_[label].key_.buf_ && kd->key_store_[label].r_ == *r) { + if(!(*r) || (seq_nr % (*r))) return 0; } - result->r_ = r; int faked_msb = 0; if(!kd->master_salt_.buf_[0]) { @@ -225,34 +262,31 @@ int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, key_store_t* result, sa } #ifndef NO_LIBGMP - mpz_t ctr, key_id; - mpz_init2(ctr, 128); - mpz_init2(key_id, 128); + mpz_import(params->mp_ctr, kd->master_salt_.length_, 1, 1, 0, 0, kd->master_salt_.buf_); - mpz_import(ctr, kd->master_salt_.length_, 1, 1, 0, 0, kd->master_salt_.buf_); - - mpz_set_ui(key_id, label); + mpz_set_ui(params->mp_key_id, label); #ifndef ANYTUN_02_COMPAT - mpz_mul_2exp(key_id, key_id, (sizeof(r) * 8)); + mpz_mul_2exp(params->mp_key_id, params->mp_key_id, (sizeof(*r) * 8)); #else - mpz_mul_2exp(key_id, key_id, 48); + mpz_mul_2exp(params->mp_key_id, params->mp_key_id, 48); #endif - mpz_add_ui(key_id, key_id, r); + mpz_add_ui(params->mp_key_id, params->mp_key_id, *r); - mpz_xor(ctr, ctr, key_id); - mpz_mul_2exp(ctr, ctr, 16); + mpz_xor(params->mp_ctr, params->mp_ctr, params->mp_key_id); + mpz_mul_2exp(params->mp_ctr, params->mp_ctr, 16); - if(result->key_.buf_) - free(result->key_.buf_); - result->key_.buf_ = mpz_export(NULL, (size_t*)&(result->key_.length_), 1, 1, 0, 0, ctr); - mpz_clear(ctr); - mpz_clear(key_id); + int out_size = (mpz_sizeinbase(params->mp_ctr, 2) + 7) / 8; + if(out_size > params->ctr_.length_) { + log_printf(ERR, "computed ctr is too big ?!?"); + return -1; + } + mpz_export(params->ctr_.buf_, NULL, 1, 1, 0, 0, params->mp_ctr); #endif #ifndef ANYTUN_02_COMPAT if(faked_msb) { kd->master_salt_.buf_[0] = 0; - result->key_.buf_[0] = 0; + params->ctr_.buf_[0] = 0; } #endif @@ -261,16 +295,19 @@ int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, key_store_t* result, sa int key_derivation_aesctr_generate(key_derivation_t* kd, satp_prf_label_t label, seq_nr_t seq_nr, u_int8_t* key, u_int32_t len) { - if(!kd || !kd->master_key_.buf_ || !kd->master_salt_.buf_) { + if(!kd || !kd->params_ || !kd->master_key_.buf_ || !kd->master_salt_.buf_) { + log_printf(ERR, "key derivation not initialized or no key or salt set"); + return -1; + } + + key_derivation_aesctr_param_t* params = kd->params_; + if(!params->ctr_.buf_) { log_printf(ERR, "key derivation not initialized or no key or salt set"); return -1; } - key_store_t ctr; - ctr.key_.buf_ = NULL; - ctr.key_.length_ = 0; - ctr.r_ = 0; - int ret = key_derivation_aesctr_calc_ctr(kd, &ctr, label, seq_nr); + seq_nr_t r; + int ret = key_derivation_aesctr_calc_ctr(kd, &r, label, seq_nr); if(ret < 0) { log_printf(ERR, "failed to calculate key derivation CTR"); return -1; @@ -285,14 +322,13 @@ int key_derivation_aesctr_generate(key_derivation_t* kd, satp_prf_label_t label, return 0; } - gcry_error_t err = gcry_cipher_reset(kd->handle_); + gcry_error_t err = gcry_cipher_reset(params->handle_); if(err) { log_printf(ERR, "failed to reset key derivation cipher: %s/%s", gcry_strerror(err), gcry_strsource(err)); return -1; } - err = gcry_cipher_setctr(kd->handle_, ctr.key_.buf_, ctr.key_.length_); - free(ctr.key_.buf_); + err = gcry_cipher_setctr(params->handle_, params->ctr_.buf_, params->ctr_.length_); if(err) { log_printf(ERR, "failed to set key derivation CTR: %s/%s", gcry_strerror(err), gcry_strsource(err)); @@ -300,7 +336,7 @@ int key_derivation_aesctr_generate(key_derivation_t* kd, satp_prf_label_t label, } memset(key, 0, len); - err = gcry_cipher_encrypt(kd->handle_, key, len, NULL, 0); + err = gcry_cipher_encrypt(params->handle_, key, len, NULL, 0); if(err) { log_printf(ERR, "failed to generate key derivation bitstream: %s/%s", gcry_strerror(err), gcry_strsource(err)); return -1; @@ -327,7 +363,7 @@ int key_derivation_aesctr_generate(key_derivation_t* kd, satp_prf_label_t label, } memcpy(kd->key_store_[label].key_.buf_, key, len); - kd->key_store_[label].r_ = ctr.r_; + kd->key_store_[label].r_ = r; return 1; } |