src/core/ngx_sha1.c - nginx source code

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Maxim Dounin
  3. * Copyright (C) Nginx, Inc.
  4. *
  5. * An internal SHA1 implementation.
  6. */


  7. #include <ngx_config.h>
  8. #include <ngx_core.h>
  9. #include <ngx_sha1.h>


  10. static const u_char *ngx_sha1_body(ngx_sha1_t *ctx, const u_char *data,
  11.     size_t size);


  12. void
  13. ngx_sha1_init(ngx_sha1_t *ctx)
  14. {
  15.     ctx->a = 0x67452301;
  16.     ctx->b = 0xefcdab89;
  17.     ctx->c = 0x98badcfe;
  18.     ctx->d = 0x10325476;
  19.     ctx->e = 0xc3d2e1f0;

  20.     ctx->bytes = 0;
  21. }


  22. void
  23. ngx_sha1_update(ngx_sha1_t *ctx, const void *data, size_t size)
  24. {
  25.     size_t  used, free;

  26.     used = (size_t) (ctx->bytes & 0x3f);
  27.     ctx->bytes += size;

  28.     if (used) {
  29.         free = 64 - used;

  30.         if (size < free) {
  31.             ngx_memcpy(&ctx->buffer[used], data, size);
  32.             return;
  33.         }

  34.         ngx_memcpy(&ctx->buffer[used], data, free);
  35.         data = (u_char *) data + free;
  36.         size -= free;
  37.         (void) ngx_sha1_body(ctx, ctx->buffer, 64);
  38.     }

  39.     if (size >= 64) {
  40.         data = ngx_sha1_body(ctx, data, size & ~(size_t) 0x3f);
  41.         size &= 0x3f;
  42.     }

  43.     ngx_memcpy(ctx->buffer, data, size);
  44. }


  45. void
  46. ngx_sha1_final(u_char result[20], ngx_sha1_t *ctx)
  47. {
  48.     size_t  used, free;

  49.     used = (size_t) (ctx->bytes & 0x3f);

  50.     ctx->buffer[used++] = 0x80;

  51.     free = 64 - used;

  52.     if (free < 8) {
  53.         ngx_memzero(&ctx->buffer[used], free);
  54.         (void) ngx_sha1_body(ctx, ctx->buffer, 64);
  55.         used = 0;
  56.         free = 64;
  57.     }

  58.     ngx_memzero(&ctx->buffer[used], free - 8);

  59.     ctx->bytes <<= 3;
  60.     ctx->buffer[56] = (u_char) (ctx->bytes >> 56);
  61.     ctx->buffer[57] = (u_char) (ctx->bytes >> 48);
  62.     ctx->buffer[58] = (u_char) (ctx->bytes >> 40);
  63.     ctx->buffer[59] = (u_char) (ctx->bytes >> 32);
  64.     ctx->buffer[60] = (u_char) (ctx->bytes >> 24);
  65.     ctx->buffer[61] = (u_char) (ctx->bytes >> 16);
  66.     ctx->buffer[62] = (u_char) (ctx->bytes >> 8);
  67.     ctx->buffer[63] = (u_char) ctx->bytes;

  68.     (void) ngx_sha1_body(ctx, ctx->buffer, 64);

  69.     result[0] = (u_char) (ctx->a >> 24);
  70.     result[1] = (u_char) (ctx->a >> 16);
  71.     result[2] = (u_char) (ctx->a >> 8);
  72.     result[3] = (u_char) ctx->a;
  73.     result[4] = (u_char) (ctx->b >> 24);
  74.     result[5] = (u_char) (ctx->b >> 16);
  75.     result[6] = (u_char) (ctx->b >> 8);
  76.     result[7] = (u_char) ctx->b;
  77.     result[8] = (u_char) (ctx->c >> 24);
  78.     result[9] = (u_char) (ctx->c >> 16);
  79.     result[10] = (u_char) (ctx->c >> 8);
  80.     result[11] = (u_char) ctx->c;
  81.     result[12] = (u_char) (ctx->d >> 24);
  82.     result[13] = (u_char) (ctx->d >> 16);
  83.     result[14] = (u_char) (ctx->d >> 8);
  84.     result[15] = (u_char) ctx->d;
  85.     result[16] = (u_char) (ctx->e >> 24);
  86.     result[17] = (u_char) (ctx->e >> 16);
  87.     result[18] = (u_char) (ctx->e >> 8);
  88.     result[19] = (u_char) ctx->e;

  89.     ngx_memzero(ctx, sizeof(*ctx));
  90. }


  91. /*
  92. * Helper functions.
  93. */

  94. #define ROTATE(bits, word)  (((word) << (bits)) | ((word) >> (32 - (bits))))

  95. #define F1(b, c, d)  (((b) & (c)) | ((~(b)) & (d)))
  96. #define F2(b, c, d)  ((b) ^ (c) ^ (d))
  97. #define F3(b, c, d)  (((b) & (c)) | ((b) & (d)) | ((c) & (d)))

  98. #define STEP(f, a, b, c, d, e, w, t)                                          \
  99.     temp = ROTATE(5, (a)) + f((b), (c), (d)) + (e) + (w) + (t);               \
  100.     (e) = (d);                                                                \
  101.     (d) = (c);                                                                \
  102.     (c) = ROTATE(30, (b));                                                    \
  103.     (b) = (a);                                                                \
  104.     (a) = temp;


  105. /*
  106. * GET() reads 4 input bytes in big-endian byte order and returns
  107. * them as uint32_t.
  108. */

  109. #define GET(n)                                                                \
  110.     ((uint32_t) p[n * 4 + 3] |                                                \
  111.     ((uint32_t) p[n * 4 + 2] << 8) |                                          \
  112.     ((uint32_t) p[n * 4 + 1] << 16) |                                         \
  113.     ((uint32_t) p[n * 4] << 24))


  114. /*
  115. * This processes one or more 64-byte data blocks, but does not update
  116. * the bit counters.  There are no alignment requirements.
  117. */

  118. static const u_char *
  119. ngx_sha1_body(ngx_sha1_t *ctx, const u_char *data, size_t size)
  120. {
  121.     uint32_t       a, b, c, d, e, temp;
  122.     uint32_t       saved_a, saved_b, saved_c, saved_d, saved_e;
  123.     uint32_t       words[80];
  124.     ngx_uint_t     i;
  125.     const u_char  *p;

  126.     p = data;

  127.     a = ctx->a;
  128.     b = ctx->b;
  129.     c = ctx->c;
  130.     d = ctx->d;
  131.     e = ctx->e;

  132.     do {
  133.         saved_a = a;
  134.         saved_b = b;
  135.         saved_c = c;
  136.         saved_d = d;
  137.         saved_e = e;

  138.         /* Load data block into the words array */

  139.         for (i = 0; i < 16; i++) {
  140.             words[i] = GET(i);
  141.         }

  142.         for (i = 16; i < 80; i++) {
  143.             words[i] = ROTATE(1, words[i - 3] ^ words[i - 8] ^ words[i - 14]
  144.                                  ^ words[i - 16]);
  145.         }

  146.         /* Transformations */

  147.         STEP(F1, a, b, c, d, e, words[0],  0x5a827999);
  148.         STEP(F1, a, b, c, d, e, words[1],  0x5a827999);
  149.         STEP(F1, a, b, c, d, e, words[2],  0x5a827999);
  150.         STEP(F1, a, b, c, d, e, words[3],  0x5a827999);
  151.         STEP(F1, a, b, c, d, e, words[4],  0x5a827999);
  152.         STEP(F1, a, b, c, d, e, words[5],  0x5a827999);
  153.         STEP(F1, a, b, c, d, e, words[6],  0x5a827999);
  154.         STEP(F1, a, b, c, d, e, words[7],  0x5a827999);
  155.         STEP(F1, a, b, c, d, e, words[8],  0x5a827999);
  156.         STEP(F1, a, b, c, d, e, words[9],  0x5a827999);
  157.         STEP(F1, a, b, c, d, e, words[10], 0x5a827999);
  158.         STEP(F1, a, b, c, d, e, words[11], 0x5a827999);
  159.         STEP(F1, a, b, c, d, e, words[12], 0x5a827999);
  160.         STEP(F1, a, b, c, d, e, words[13], 0x5a827999);
  161.         STEP(F1, a, b, c, d, e, words[14], 0x5a827999);
  162.         STEP(F1, a, b, c, d, e, words[15], 0x5a827999);
  163.         STEP(F1, a, b, c, d, e, words[16], 0x5a827999);
  164.         STEP(F1, a, b, c, d, e, words[17], 0x5a827999);
  165.         STEP(F1, a, b, c, d, e, words[18], 0x5a827999);
  166.         STEP(F1, a, b, c, d, e, words[19], 0x5a827999);

  167.         STEP(F2, a, b, c, d, e, words[20], 0x6ed9eba1);
  168.         STEP(F2, a, b, c, d, e, words[21], 0x6ed9eba1);
  169.         STEP(F2, a, b, c, d, e, words[22], 0x6ed9eba1);
  170.         STEP(F2, a, b, c, d, e, words[23], 0x6ed9eba1);
  171.         STEP(F2, a, b, c, d, e, words[24], 0x6ed9eba1);
  172.         STEP(F2, a, b, c, d, e, words[25], 0x6ed9eba1);
  173.         STEP(F2, a, b, c, d, e, words[26], 0x6ed9eba1);
  174.         STEP(F2, a, b, c, d, e, words[27], 0x6ed9eba1);
  175.         STEP(F2, a, b, c, d, e, words[28], 0x6ed9eba1);
  176.         STEP(F2, a, b, c, d, e, words[29], 0x6ed9eba1);
  177.         STEP(F2, a, b, c, d, e, words[30], 0x6ed9eba1);
  178.         STEP(F2, a, b, c, d, e, words[31], 0x6ed9eba1);
  179.         STEP(F2, a, b, c, d, e, words[32], 0x6ed9eba1);
  180.         STEP(F2, a, b, c, d, e, words[33], 0x6ed9eba1);
  181.         STEP(F2, a, b, c, d, e, words[34], 0x6ed9eba1);
  182.         STEP(F2, a, b, c, d, e, words[35], 0x6ed9eba1);
  183.         STEP(F2, a, b, c, d, e, words[36], 0x6ed9eba1);
  184.         STEP(F2, a, b, c, d, e, words[37], 0x6ed9eba1);
  185.         STEP(F2, a, b, c, d, e, words[38], 0x6ed9eba1);
  186.         STEP(F2, a, b, c, d, e, words[39], 0x6ed9eba1);

  187.         STEP(F3, a, b, c, d, e, words[40], 0x8f1bbcdc);
  188.         STEP(F3, a, b, c, d, e, words[41], 0x8f1bbcdc);
  189.         STEP(F3, a, b, c, d, e, words[42], 0x8f1bbcdc);
  190.         STEP(F3, a, b, c, d, e, words[43], 0x8f1bbcdc);
  191.         STEP(F3, a, b, c, d, e, words[44], 0x8f1bbcdc);
  192.         STEP(F3, a, b, c, d, e, words[45], 0x8f1bbcdc);
  193.         STEP(F3, a, b, c, d, e, words[46], 0x8f1bbcdc);
  194.         STEP(F3, a, b, c, d, e, words[47], 0x8f1bbcdc);
  195.         STEP(F3, a, b, c, d, e, words[48], 0x8f1bbcdc);
  196.         STEP(F3, a, b, c, d, e, words[49], 0x8f1bbcdc);
  197.         STEP(F3, a, b, c, d, e, words[50], 0x8f1bbcdc);
  198.         STEP(F3, a, b, c, d, e, words[51], 0x8f1bbcdc);
  199.         STEP(F3, a, b, c, d, e, words[52], 0x8f1bbcdc);
  200.         STEP(F3, a, b, c, d, e, words[53], 0x8f1bbcdc);
  201.         STEP(F3, a, b, c, d, e, words[54], 0x8f1bbcdc);
  202.         STEP(F3, a, b, c, d, e, words[55], 0x8f1bbcdc);
  203.         STEP(F3, a, b, c, d, e, words[56], 0x8f1bbcdc);
  204.         STEP(F3, a, b, c, d, e, words[57], 0x8f1bbcdc);
  205.         STEP(F3, a, b, c, d, e, words[58], 0x8f1bbcdc);
  206.         STEP(F3, a, b, c, d, e, words[59], 0x8f1bbcdc);

  207.         STEP(F2, a, b, c, d, e, words[60], 0xca62c1d6);
  208.         STEP(F2, a, b, c, d, e, words[61], 0xca62c1d6);
  209.         STEP(F2, a, b, c, d, e, words[62], 0xca62c1d6);
  210.         STEP(F2, a, b, c, d, e, words[63], 0xca62c1d6);
  211.         STEP(F2, a, b, c, d, e, words[64], 0xca62c1d6);
  212.         STEP(F2, a, b, c, d, e, words[65], 0xca62c1d6);
  213.         STEP(F2, a, b, c, d, e, words[66], 0xca62c1d6);
  214.         STEP(F2, a, b, c, d, e, words[67], 0xca62c1d6);
  215.         STEP(F2, a, b, c, d, e, words[68], 0xca62c1d6);
  216.         STEP(F2, a, b, c, d, e, words[69], 0xca62c1d6);
  217.         STEP(F2, a, b, c, d, e, words[70], 0xca62c1d6);
  218.         STEP(F2, a, b, c, d, e, words[71], 0xca62c1d6);
  219.         STEP(F2, a, b, c, d, e, words[72], 0xca62c1d6);
  220.         STEP(F2, a, b, c, d, e, words[73], 0xca62c1d6);
  221.         STEP(F2, a, b, c, d, e, words[74], 0xca62c1d6);
  222.         STEP(F2, a, b, c, d, e, words[75], 0xca62c1d6);
  223.         STEP(F2, a, b, c, d, e, words[76], 0xca62c1d6);
  224.         STEP(F2, a, b, c, d, e, words[77], 0xca62c1d6);
  225.         STEP(F2, a, b, c, d, e, words[78], 0xca62c1d6);
  226.         STEP(F2, a, b, c, d, e, words[79], 0xca62c1d6);

  227.         a += saved_a;
  228.         b += saved_b;
  229.         c += saved_c;
  230.         d += saved_d;
  231.         e += saved_e;

  232.         p += 64;

  233.     } while (size -= 64);

  234.     ctx->a = a;
  235.     ctx->b = b;
  236.     ctx->c = c;
  237.     ctx->d = d;
  238.     ctx->e = e;

  239.     return p;
  240. }