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.

80 regels
2.2 KiB

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