fix
[libpgclient.git] / src / md5.c
blobb371bd479c7c4451547e9dc113f381fe3dbea090
1 /*Copyright (c) Brian B.
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Lesser General Public
5 License as published by the Free Software Foundation; either
6 version 3 of the License, or (at your option) any later version.
7 See the file LICENSE included with this distribution for more
8 information.
9 */
10 #include "md5.h"
12 #define A 0x67452301
13 #define B 0xefcdab89
14 #define C 0x98badcfe
15 #define D 0x10325476
17 static uint32_t S[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
18 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
19 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
20 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
22 static uint32_t K[] = {0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
23 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
24 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
25 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
26 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
27 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
28 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
29 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
30 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
31 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
32 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
33 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
34 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
35 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
36 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
37 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};
39 #define F(X, Y, Z) ((X & Y) | (~X & Z))
40 #define G(X, Y, Z) ((X & Z) | (Y & ~Z))
41 #define H(X, Y, Z) (X ^ Y ^ Z)
42 #define I(X, Y, Z) (Y ^ (X | ~Z))
44 static uint8_t PADDING[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
53 void md5_init(md5_t *ctx){
54 ctx->size = (uint64_t)0;
56 ctx->buffer[0] = (uint32_t)A;
57 ctx->buffer[1] = (uint32_t)B;
58 ctx->buffer[2] = (uint32_t)C;
59 ctx->buffer[3] = (uint32_t)D;
62 uint32_t rotate_left(uint32_t x, uint32_t n){
63 return (x << n) | (x >> (32 - n));
66 static void md5_step(uint32_t *buffer, uint32_t *input){
67 uint32_t AA = buffer[0];
68 uint32_t BB = buffer[1];
69 uint32_t CC = buffer[2];
70 uint32_t DD = buffer[3];
72 uint32_t E;
74 unsigned int j;
76 for(unsigned int i = 0; i < 64; ++i){
77 switch(i / 16){
78 case 0:
79 E = F(BB, CC, DD);
80 j = i;
81 break;
82 case 1:
83 E = G(BB, CC, DD);
84 j = ((i * 5) + 1) % 16;
85 break;
86 case 2:
87 E = H(BB, CC, DD);
88 j = ((i * 3) + 5) % 16;
89 break;
90 default:
91 E = I(BB, CC, DD);
92 j = (i * 7) % 16;
93 break;
96 uint32_t temp = DD;
97 DD = CC;
98 CC = BB;
99 BB = BB + rotate_left(AA + E + K[i] + input[j], S[i]);
100 AA = temp;
103 buffer[0] += AA;
104 buffer[1] += BB;
105 buffer[2] += CC;
106 buffer[3] += DD;
108 void md5_update(md5_t *ctx, uint8_t *input_buffer, size_t input_len){
109 uint32_t input[16];
110 unsigned int offset = ctx->size % 64;
111 ctx->size += (uint64_t)input_len;
113 for(unsigned int i = 0; i < input_len; ++i){
114 ctx->input[offset++] = (uint8_t)*(input_buffer + i);
115 if(offset % 64 == 0){
116 for(unsigned int j = 0; j < 16; ++j){
117 input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 |
118 (uint32_t)(ctx->input[(j * 4) + 2]) << 16 |
119 (uint32_t)(ctx->input[(j * 4) + 1]) << 8 |
120 (uint32_t)(ctx->input[(j * 4)]);
122 md5_step(ctx->buffer, input);
123 offset = 0;
128 void md5_final(md5_t *ctx){
129 uint32_t input[16];
130 unsigned int offset = ctx->size % 64;
131 unsigned int padding_length = offset < 56 ? 56 - offset : (56 + 64) - offset;
133 md5_update(ctx, PADDING, padding_length);
134 ctx->size -= (uint64_t)padding_length;
136 for(unsigned int j = 0; j < 14; ++j){
137 input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 |
138 (uint32_t)(ctx->input[(j * 4) + 2]) << 16 |
139 (uint32_t)(ctx->input[(j * 4) + 1]) << 8 |
140 (uint32_t)(ctx->input[(j * 4)]);
142 input[14] = (uint32_t)(ctx->size * 8);
143 input[15] = (uint32_t)((ctx->size * 8) >> 32);
145 md5_step(ctx->buffer, input);
147 for(unsigned int i = 0; i < 4; ++i){
148 ctx->digest[(i * 4) + 0] = (uint8_t)((ctx->buffer[i] & 0x000000FF));
149 ctx->digest[(i * 4) + 1] = (uint8_t)((ctx->buffer[i] & 0x0000FF00) >> 8);
150 ctx->digest[(i * 4) + 2] = (uint8_t)((ctx->buffer[i] & 0x00FF0000) >> 16);
151 ctx->digest[(i * 4) + 3] = (uint8_t)((ctx->buffer[i] & 0xFF000000) >> 24);