crypto_session.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "crypto_aes.h"
  5. #include "crypto_aesctr.h"
  6. #include "crypto_dh.h"
  7. #include "crypto_verify_bytes.h"
  8. #include "sysendian.h"
  9. #include "crypto_internal.h"
  10. #include "crypto.h"
  11. struct crypto_session_internal {
  12. struct crypto_aesctr * encr_write_stream;
  13. struct crypto_aes_key * encr_write;
  14. uint8_t auth_write[32];
  15. uint64_t auth_write_nonce;
  16. struct crypto_aesctr * encr_read_stream;
  17. struct crypto_aes_key * encr_read;
  18. uint8_t auth_read[32];
  19. uint64_t auth_read_nonce;
  20. };
  21. /**
  22. * crypto_session_init(pub, priv, nonce, mkey, encr_write, auth_write,
  23. * encr_read, auth_read):
  24. * Compute K = ${pub}^(2^258 + ${priv}), mkey = MGF1(nonce || K, 48), and
  25. * return a CRYPTO_SESSION with encryption and authentication write and read
  26. * keys constructed from HMAC(mkey, (encr|auth)_(write|read)).
  27. */
  28. CRYPTO_SESSION *
  29. crypto_session_init(uint8_t pub[CRYPTO_DH_PUBLEN],
  30. uint8_t priv[CRYPTO_DH_PRIVLEN], uint8_t nonce[32], uint8_t mkey[48],
  31. const char * encr_write, const char * auth_write,
  32. const char * encr_read, const char * auth_read)
  33. {
  34. struct crypto_session_internal * CS;
  35. uint8_t K[CRYPTO_DH_PUBLEN];
  36. uint8_t MGFbuf[32 + CRYPTO_DH_PUBLEN];
  37. uint8_t aes_write[32];
  38. uint8_t aes_read[32];
  39. /* Compute K = 2^(xy) mod p. */
  40. if (crypto_dh_compute(pub, priv, K))
  41. goto err0;
  42. /* Shared key is MGF1(nonce || K, 48). */
  43. memcpy(MGFbuf, nonce, 32);
  44. memcpy(MGFbuf + 32, K, CRYPTO_DH_PUBLEN);
  45. crypto_MGF1(MGFbuf, 32 + CRYPTO_DH_PUBLEN, mkey, 48);
  46. /* Allocate space for session key structure. */
  47. if ((CS = malloc(sizeof(struct crypto_session_internal))) == NULL)
  48. goto err0;
  49. /* Generate raw keys. */
  50. crypto_hash_data_key(mkey, 48,
  51. (const uint8_t *)encr_write, strlen(encr_write), aes_write);
  52. crypto_hash_data_key(mkey, 48,
  53. (const uint8_t *)auth_write, strlen(auth_write), CS->auth_write);
  54. crypto_hash_data_key(mkey, 48,
  55. (const uint8_t *)encr_read, strlen(encr_read), aes_read);
  56. crypto_hash_data_key(mkey, 48,
  57. (const uint8_t *)auth_read, strlen(auth_read), CS->auth_read);
  58. /* Expand AES keys and set up streams. */
  59. if ((CS->encr_write = crypto_aes_key_expand(aes_write, 32)) == NULL)
  60. goto err1;
  61. if ((CS->encr_read = crypto_aes_key_expand(aes_read, 32)) == NULL)
  62. goto err2;
  63. if ((CS->encr_write_stream =
  64. crypto_aesctr_init(CS->encr_write, 0)) == NULL)
  65. goto err3;
  66. if ((CS->encr_read_stream =
  67. crypto_aesctr_init(CS->encr_read, 0)) == NULL)
  68. goto err4;
  69. /* Initialize parameters. */
  70. CS->auth_write_nonce = CS->auth_read_nonce = 0;
  71. /* Success! */
  72. return (CS);
  73. err4:
  74. crypto_aesctr_free(CS->encr_write_stream);
  75. err3:
  76. crypto_aes_key_free(CS->encr_read);
  77. err2:
  78. crypto_aes_key_free(CS->encr_write);
  79. err1:
  80. free(CS);
  81. err0:
  82. /* Failure! */
  83. return (NULL);
  84. }
  85. /**
  86. * crypto_session_encrypt(CS, inbuf, outbuf, buflen):
  87. * Encrypt ${inbuf} with the session write key and write ciphertext to
  88. * ${outbuf}.
  89. */
  90. void
  91. crypto_session_encrypt(CRYPTO_SESSION * CS, const uint8_t * inbuf,
  92. uint8_t * outbuf, size_t buflen)
  93. {
  94. crypto_aesctr_stream(CS->encr_write_stream, inbuf, outbuf, buflen);
  95. }
  96. /**
  97. * crypto_session_decrypt(CS, inbuf, outbuf, buflen):
  98. * Decrypt ${inbuf} with the session read key and write plaintext to ${outbuf}.
  99. */
  100. void
  101. crypto_session_decrypt(CRYPTO_SESSION * CS, const uint8_t * inbuf,
  102. uint8_t * outbuf, size_t buflen)
  103. {
  104. crypto_aesctr_stream(CS->encr_read_stream, inbuf, outbuf, buflen);
  105. }
  106. /**
  107. * crypto_session_sign(CS, buf, buflen, sig):
  108. * Generate sig = write_auth(buf).
  109. */
  110. void
  111. crypto_session_sign(CRYPTO_SESSION * CS, const uint8_t * buf, size_t buflen,
  112. uint8_t sig[32])
  113. {
  114. uint8_t nonce[8];
  115. /* Convert nonce to 8-byte big-endian format, and increment. */
  116. be64enc(nonce, CS->auth_write_nonce);
  117. CS->auth_write_nonce += 1;
  118. /* Generate hash. */
  119. crypto_hash_data_key_2(CS->auth_write, 32,
  120. nonce, 8, buf, buflen, sig);
  121. }
  122. /**
  123. * crypto_session_verify(CS, buf, buflen, sig):
  124. * Verify that sig = read_auth(buf). Return non-zero if the signature
  125. * does not match.
  126. */
  127. int
  128. crypto_session_verify(CRYPTO_SESSION * CS, const uint8_t * buf, size_t buflen,
  129. const uint8_t sig[32])
  130. {
  131. uint8_t nonce[8];
  132. uint8_t sig_actual[32];
  133. /* Convert nonce to 8-byte big-endian format, and increment. */
  134. be64enc(nonce, CS->auth_read_nonce);
  135. CS->auth_read_nonce += 1;
  136. /* Generate hash. */
  137. crypto_hash_data_key_2(CS->auth_read, 32,
  138. nonce, 8, buf, buflen, sig_actual);
  139. /* Determine if the signatures match. */
  140. if (crypto_verify_bytes(sig, sig_actual, 32))
  141. return (1);
  142. else
  143. return (0);
  144. }
  145. /**
  146. * crypto_session_free(CS):
  147. * Free a CRYPTO_SESSION structure.
  148. */
  149. void
  150. crypto_session_free(CRYPTO_SESSION * CS)
  151. {
  152. /* Behave consistently with free(NULL). */
  153. if (CS == NULL)
  154. return;
  155. crypto_aesctr_free(CS->encr_write_stream);
  156. crypto_aesctr_free(CS->encr_read_stream);
  157. crypto_aes_key_free(CS->encr_write);
  158. crypto_aes_key_free(CS->encr_read);
  159. free(CS);
  160. }