You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.1 KiB

  1. /*
  2. prg.c version 20151120
  3. Andreas Hülsing
  4. Public domain.
  5. */
  6. #include "chacha.h"
  7. #include "prg.h"
  8. #include <stdio.h>
  9. #include <openssl/sha.h>
  10. #include <openssl/hmac.h>
  11. #include <openssl/evp.h>
  12. const unsigned char zero_nonce[12] = {0};
  13. /**
  14. * Generates rlen output bytes using ChaCha20 with a zero nonce and counter = 0
  15. */
  16. void prg(unsigned char *r, unsigned long long rlen, const unsigned char *key, unsigned int key_len)
  17. {
  18. if(key_len == 32){
  19. CRYPTO_chacha_20_keystream(r, rlen, key, zero_nonce, 0);
  20. }
  21. else
  22. {
  23. if(key_len == 64)
  24. {
  25. unsigned long long left = rlen;
  26. u_int32_t counter = 0;
  27. unsigned char *c = (unsigned char*)&counter;
  28. unsigned int length;
  29. unsigned int i = 0;
  30. unsigned char tmp[64];
  31. while(left > 0)
  32. {
  33. HMAC(EVP_sha512(), key, key_len, c , 4, tmp, &length);
  34. if(length != 64)
  35. {
  36. fprintf(stderr, "HMAC outputs %d bytes... That should not happen...",length);
  37. }
  38. for(i = 0; ((i < length) && (i < left));i++)
  39. {
  40. r[rlen-left+i] = tmp[i];
  41. }
  42. left -=length;
  43. counter++;
  44. }
  45. }
  46. else {
  47. fprintf(stderr,"prg.c:: Code only supports 32 byte and 64 byte seeds");
  48. }
  49. }
  50. }
  51. /**
  52. * Generates n output bytes using ChaCha20 (n=32) or HMAC-SHA2-512 (n=64).
  53. *
  54. * For ChaCha, nonce and counter are set depending on the address addr. For HMAC, addr is used as message.
  55. */
  56. void prg_with_counter(unsigned char *r, const unsigned char *key, unsigned int n, const unsigned char addr[16])
  57. {
  58. int i;
  59. unsigned char nonce[12];
  60. if(n == 32){
  61. for(i = 0; i < 12; i++)
  62. {
  63. nonce[i] = addr[i];
  64. }
  65. uint32_t counter;
  66. counter = (((uint32_t)addr[12]) << 24)|(((uint32_t)addr[13]) << 16)|(((uint32_t)addr[14]) << 8)|addr[15];
  67. // TODO: Check address handling. Endianess?
  68. CRYPTO_chacha_20_keystream(r, n, key, nonce, counter);
  69. }
  70. else
  71. {
  72. if(n == 64)
  73. {
  74. unsigned int length;
  75. HMAC(EVP_sha512(), key, n, addr, 16, r, &length);
  76. if(length != 64)
  77. {
  78. fprintf(stderr, "HMAC outputs %d bytes... That should not happen...",length);
  79. }
  80. } else {
  81. fprintf(stderr,"prg.c:: Code only supports 32 byte and 64 byte seeds");
  82. }
  83. }
  84. }