prf_tls12.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* prf_tls12.c */
  2. /*
  3. This file is part of the ARM-Crypto-Lib.
  4. Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. /*
  17. * \file prf_tls12.c
  18. * \author Daniel Otte
  19. * \email daniel.otte@rub.de
  20. * \date 2011-10-06
  21. * \license GPLv3 or later
  22. *
  23. */
  24. /* from rfc5246
  25. P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
  26. HMAC_hash(secret, A(2) + seed) +
  27. HMAC_hash(secret, A(3) + seed) + ...
  28. where + indicates concatenation.
  29. A() is defined as:
  30. A(0) = seed
  31. A(i) = HMAC_hash(secret, A(i-1))
  32. P_hash can be iterated as many times as necessary to produce the
  33. required quantity of data. For example, if P_SHA256 is being used to
  34. create 80 bytes of data, it will have to be iterated three times
  35. (through A(3)), creating 96 bytes of output data; the last 16 bytes
  36. of the final iteration will then be discarded, leaving 80 bytes of
  37. output data.
  38. TLS's PRF is created by applying P_hash to the secret as:
  39. PRF(secret, label, seed) = P_<hash>(secret, label + seed)
  40. */
  41. /* long story short:
  42. * P(k,s) = H(k, A(1) | s) | H(k, A(2) | s) | ... | H(k, A(n) | s)
  43. * A(0) = s
  44. * A(i) = H(k, A(i-1))
  45. *
  46. * PRF(k,l,s) = P(k, l | s)
  47. *
  48. */
  49. /* This implementation is limited to hashfunctions which return a hash value
  50. * of a length (in bits) which is divideable by 8.
  51. *
  52. * Also note that our HMAC implementation may fail on hashfunction which
  53. * return a larger hash value then their nativ blocksize
  54. *
  55. */
  56. #include <stdint.h>
  57. #include <stdlib.h>
  58. #include <string.h>
  59. #include <crypto/hashfunction_descriptor.h>
  60. #include <crypto/hfal-basic.h>
  61. #include <crypto/hfal-hmac.h>
  62. #include <crypto/prf_tls12.h>
  63. uint8_t prf_tls12_init(prf_tls12_ctx_t* ctx, const hfdesc_t* hash,
  64. const void* key, uint16_t keylength_b,
  65. const void* seed, uint16_t seedlength_b){
  66. hfhmacgen_ctx_t tmp_ctx;
  67. ctx->blocklength_b = hfal_hash_getHashsize(hash);
  68. ctx->seed_buffer = malloc(ctx->blocklength_b/8+(seedlength_b+7)/8);
  69. if(!ctx->seed_buffer){
  70. return 1;
  71. }
  72. ctx->bufferlength_b = ctx->blocklength_b + seedlength_b;
  73. memcpy(ctx->seed_buffer+ctx->blocklength_b/8, seed, seedlength_b/8);
  74. if(hfal_hmac_init(hash, &(ctx->mainctx), key, keylength_b)){
  75. return 2;
  76. }
  77. if(hfal_hmac_ctxcopy(&tmp_ctx, &(ctx->mainctx))){
  78. prf_tls12_free(ctx);
  79. return 3;
  80. }
  81. hfal_hmac_lastBlock(&tmp_ctx, seed, seedlength_b);
  82. hfal_hmac_ctx2mac(ctx->seed_buffer, &tmp_ctx);
  83. hfal_hmac_free(&tmp_ctx);
  84. return 0;
  85. }
  86. uint8_t prf_tls12_init_w_label(prf_tls12_ctx_t* ctx, const hfdesc_t* hash,
  87. const void* key, uint16_t keylength_b,
  88. const void* label, uint16_t labellength_B,
  89. const void* seed, uint16_t seedlength_b){
  90. uint8_t buffer[labellength_B+(seedlength_b+7)/8];
  91. memcpy(buffer, label, labellength_B);
  92. memcpy(buffer+labellength_B, seed, (seedlength_b+7)/8);
  93. return prf_tls12_init(ctx, hash, key, keylength_b, buffer, labellength_B*8+seedlength_b);
  94. }
  95. void prf_tls12_free(prf_tls12_ctx_t* ctx){
  96. free(ctx->seed_buffer);
  97. hfal_hmac_free(&(ctx->mainctx));
  98. }
  99. uint8_t prf_tls12_next(void* dest, prf_tls12_ctx_t* ctx){
  100. hfhmacgen_ctx_t tmp_ctx;
  101. if(hfal_hmac_ctxcopy(&tmp_ctx, &(ctx->mainctx))){
  102. return 1;
  103. }
  104. hfal_hmac_lastBlock(&tmp_ctx, ctx->seed_buffer, ctx->bufferlength_b);
  105. hfal_hmac_ctx2mac(dest, &tmp_ctx);
  106. hfal_hmac_free(&tmp_ctx);
  107. if(hfal_hmac_ctxcopy(&tmp_ctx, &(ctx->mainctx))){
  108. return 2;
  109. }
  110. hfal_hmac_lastBlock(&tmp_ctx, ctx->seed_buffer, ctx->blocklength_b);
  111. hfal_hmac_ctx2mac(ctx->seed_buffer, &tmp_ctx);
  112. hfal_hmac_free(&tmp_ctx);
  113. return 0;
  114. }
  115. uint8_t prf_tls12_fill(void* dest, uint16_t length_B, prf_tls12_ctx_t* ctx){
  116. uint16_t bs = ctx->blocklength_b/8;
  117. while(length_B>=bs){
  118. if(prf_tls12_next(dest, ctx)){
  119. return 1;
  120. }
  121. length_B -= bs;
  122. dest = (uint8_t*)dest + bs;
  123. }
  124. if(length_B){
  125. uint8_t buffer[bs];
  126. if(prf_tls12_next(buffer, ctx)){
  127. return 2;
  128. }
  129. memcpy(dest, buffer, length_B);
  130. }
  131. return 0;
  132. }