gost_keywrap.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /**********************************************************************
  2. * keywrap.c *
  3. * Copyright (c) 2005-2006 Cryptocom LTD *
  4. * This file is distributed under the same license as OpenSSL *
  5. * *
  6. * Implementation of CryptoPro key wrap algorithm, as defined in *
  7. * RFC 4357 p 6.3 and 6.4 *
  8. * Doesn't need OpenSSL *
  9. **********************************************************************/
  10. #include <string.h>
  11. #include "gost89.h"
  12. #include "gost_keywrap.h"
  13. /*-
  14. * Diversifies key using random UserKey Material
  15. * Implements RFC 4357 p 6.5 key diversification algorithm
  16. *
  17. * inputKey - 32byte key to be diversified
  18. * ukm - 8byte user key material
  19. * outputKey - 32byte buffer to store diversified key
  20. *
  21. */
  22. void keyDiversifyCryptoPro(gost_ctx * ctx, const unsigned char *inputKey,
  23. const unsigned char *ukm, unsigned char *outputKey)
  24. {
  25. u4 k, s1, s2;
  26. int i, j, mask;
  27. unsigned char S[8];
  28. memcpy(outputKey, inputKey, 32);
  29. for (i = 0; i < 8; i++) {
  30. /* Make array of integers from key */
  31. /* Compute IV S */
  32. s1 = 0, s2 = 0;
  33. for (j = 0, mask = 1; j < 8; j++, mask <<= 1) {
  34. k = ((u4) outputKey[4 * j]) | (outputKey[4 * j + 1] << 8) |
  35. (outputKey[4 * j + 2] << 16) | (outputKey[4 * j + 3] << 24);
  36. if (mask & ukm[i]) {
  37. s1 += k;
  38. } else {
  39. s2 += k;
  40. }
  41. }
  42. S[0] = (unsigned char)(s1 & 0xff);
  43. S[1] = (unsigned char)((s1 >> 8) & 0xff);
  44. S[2] = (unsigned char)((s1 >> 16) & 0xff);
  45. S[3] = (unsigned char)((s1 >> 24) & 0xff);
  46. S[4] = (unsigned char)(s2 & 0xff);
  47. S[5] = (unsigned char)((s2 >> 8) & 0xff);
  48. S[6] = (unsigned char)((s2 >> 16) & 0xff);
  49. S[7] = (unsigned char)((s2 >> 24) & 0xff);
  50. gost_key(ctx, outputKey);
  51. gost_enc_cfb(ctx, S, outputKey, outputKey, 4);
  52. }
  53. }
  54. /*-
  55. * Wraps key using RFC 4357 6.3
  56. * ctx - gost encryption context, initialized with some S-boxes
  57. * keyExchangeKey (KEK) 32-byte (256-bit) shared key
  58. * ukm - 8 byte (64 bit) user key material,
  59. * sessionKey - 32-byte (256-bit) key to be wrapped
  60. * wrappedKey - 44-byte buffer to store wrapped key
  61. */
  62. int keyWrapCryptoPro(gost_ctx * ctx, const unsigned char *keyExchangeKey,
  63. const unsigned char *ukm,
  64. const unsigned char *sessionKey,
  65. unsigned char *wrappedKey)
  66. {
  67. unsigned char kek_ukm[32];
  68. keyDiversifyCryptoPro(ctx, keyExchangeKey, ukm, kek_ukm);
  69. gost_key(ctx, kek_ukm);
  70. memcpy(wrappedKey, ukm, 8);
  71. gost_enc(ctx, sessionKey, wrappedKey + 8, 4);
  72. gost_mac_iv(ctx, 32, ukm, sessionKey, 32, wrappedKey + 40);
  73. return 1;
  74. }
  75. /*-
  76. * Unwraps key using RFC 4357 6.4
  77. * ctx - gost encryption context, initialized with some S-boxes
  78. * keyExchangeKey 32-byte shared key
  79. * wrappedKey 44 byte key to be unwrapped (concatenation of 8-byte UKM,
  80. * 32 byte encrypted key and 4 byte MAC
  81. *
  82. * sessionKEy - 32byte buffer to store sessionKey in
  83. * Returns 1 if key is decrypted successfully, and 0 if MAC doesn't match
  84. */
  85. int keyUnwrapCryptoPro(gost_ctx * ctx, const unsigned char *keyExchangeKey,
  86. const unsigned char *wrappedKey,
  87. unsigned char *sessionKey)
  88. {
  89. unsigned char kek_ukm[32], cek_mac[4];
  90. keyDiversifyCryptoPro(ctx, keyExchangeKey, wrappedKey
  91. /* First 8 bytes of wrapped Key is ukm */
  92. , kek_ukm);
  93. gost_key(ctx, kek_ukm);
  94. gost_dec(ctx, wrappedKey + 8, sessionKey, 4);
  95. gost_mac_iv(ctx, 32, wrappedKey, sessionKey, 32, cek_mac);
  96. if (memcmp(cek_mac, wrappedKey + 40, 4)) {
  97. return 0;
  98. }
  99. return 1;
  100. }