tpm2_kdfa.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. #include <string.h>
  3. #include "log.h"
  4. #include "tpm2_kdfa.h"
  5. #include "tpm2_openssl.h"
  6. TSS2_RC tpm2_kdfa(TPMI_ALG_HASH hash_alg, TPM2B *key, char *label,
  7. TPM2B *context_u, TPM2B *context_v, UINT16 bits,
  8. TPM2B_MAX_BUFFER *result_key) {
  9. TPM2B_DIGEST tpm2b_label, tpm2b_bits, tpm2b_i_2;
  10. TPM2B_DIGEST *buffer_list[8];
  11. TSS2_RC rval = TPM2_RC_SUCCESS;
  12. int i, j;
  13. UINT16 bytes = bits / 8;
  14. result_key->size = 0;
  15. tpm2b_i_2.size = 4;
  16. tpm2b_bits.size = 4;
  17. UINT32 bits_be = tpm2_util_hton_32(bits);
  18. memcpy(&tpm2b_bits.buffer[0], &bits_be, sizeof(bits_be));
  19. for(i = 0; label[i] != 0 ;i++ );
  20. tpm2b_label.size = i + 1;
  21. for (i = 0; i < tpm2b_label.size; i++) {
  22. tpm2b_label.buffer[i] = label[i];
  23. }
  24. result_key->size = 0;
  25. i = 1;
  26. const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(hash_alg);
  27. if (!md) {
  28. LOG_ERR("Algorithm not supported for hmac: %x", hash_alg);
  29. return TPM2_RC_HASH;
  30. }
  31. HMAC_CTX *ctx = tpm2_openssl_hmac_new();
  32. if (!ctx) {
  33. LOG_ERR("HMAC context allocation failed");
  34. return TPM2_RC_MEMORY;
  35. }
  36. int rc = HMAC_Init_ex(ctx, key->buffer, key->size, md, NULL);
  37. if (!rc) {
  38. LOG_ERR("HMAC Init failed: %s", ERR_error_string(rc, NULL));
  39. rval = TPM2_RC_MEMORY;
  40. goto err;
  41. }
  42. // TODO Why is this a loop? It appears to only execute once.
  43. while (result_key->size < bytes) {
  44. TPM2B_DIGEST tmpResult;
  45. // Inner loop
  46. bits_be = tpm2_util_hton_32(i);
  47. memcpy(&tpm2b_i_2.buffer[0], &bits_be, sizeof(bits_be));
  48. j = 0;
  49. buffer_list[j++] = (TPM2B_DIGEST *) &(tpm2b_i_2);
  50. buffer_list[j++] = (TPM2B_DIGEST *) &(tpm2b_label);
  51. buffer_list[j++] = (TPM2B_DIGEST *) context_u;
  52. buffer_list[j++] = (TPM2B_DIGEST *) context_v;
  53. buffer_list[j++] = (TPM2B_DIGEST *) &(tpm2b_bits);
  54. buffer_list[j] = (TPM2B_DIGEST *) 0;
  55. int c;
  56. for (c = 0; c < j; c++) {
  57. TPM2B_DIGEST *digest = buffer_list[c];
  58. int rc = HMAC_Update(ctx, digest->buffer, digest->size);
  59. if (!rc) {
  60. LOG_ERR("HMAC Update failed: %s", ERR_error_string(rc, NULL));
  61. rval = TPM2_RC_MEMORY;
  62. goto err;
  63. }
  64. }
  65. unsigned size = sizeof(tmpResult.buffer);
  66. int rc = HMAC_Final(ctx, tmpResult.buffer, &size);
  67. if (!rc) {
  68. LOG_ERR("HMAC Final failed: %s", ERR_error_string(rc, NULL));
  69. rval = TPM2_RC_MEMORY;
  70. goto err;
  71. }
  72. tmpResult.size = size;
  73. bool res = tpm2_util_concat_buffer(result_key, (TPM2B *) &tmpResult);
  74. if (!res) {
  75. rval = TSS2_SYS_RC_BAD_VALUE;
  76. goto err;
  77. }
  78. }
  79. // Truncate the result to the desired size.
  80. result_key->size = bytes;
  81. err:
  82. tpm2_openssl_hmac_free(ctx);
  83. return rval;
  84. }