/* +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Sara Golemon | +----------------------------------------------------------------------+ */ /* Heavily borrowed from md5.c & sha1.c of PHP archival fame Note that ripemd laughs in the face of logic and uses little endian byte ordering */ #include "php_hash.h" #include "php_hash_ripemd.h" const php_hash_ops php_hash_ripemd128_ops = { "ripemd128", (php_hash_init_func_t) PHP_RIPEMD128Init, (php_hash_update_func_t) PHP_RIPEMD128Update, (php_hash_final_func_t) PHP_RIPEMD128Final, php_hash_copy, php_hash_serialize, php_hash_unserialize, PHP_RIPEMD128_SPEC, 16, 64, sizeof(PHP_RIPEMD128_CTX), 1 }; const php_hash_ops php_hash_ripemd160_ops = { "ripemd160", (php_hash_init_func_t) PHP_RIPEMD160Init, (php_hash_update_func_t) PHP_RIPEMD160Update, (php_hash_final_func_t) PHP_RIPEMD160Final, php_hash_copy, php_hash_serialize, php_hash_unserialize, PHP_RIPEMD160_SPEC, 20, 64, sizeof(PHP_RIPEMD160_CTX), 1 }; const php_hash_ops php_hash_ripemd256_ops = { "ripemd256", (php_hash_init_func_t) PHP_RIPEMD256Init, (php_hash_update_func_t) PHP_RIPEMD256Update, (php_hash_final_func_t) PHP_RIPEMD256Final, php_hash_copy, php_hash_serialize, php_hash_unserialize, PHP_RIPEMD256_SPEC, 32, 64, sizeof(PHP_RIPEMD256_CTX), 1 }; const php_hash_ops php_hash_ripemd320_ops = { "ripemd320", (php_hash_init_func_t) PHP_RIPEMD320Init, (php_hash_update_func_t) PHP_RIPEMD320Update, (php_hash_final_func_t) PHP_RIPEMD320Final, php_hash_copy, php_hash_serialize, php_hash_unserialize, PHP_RIPEMD320_SPEC, 40, 64, sizeof(PHP_RIPEMD320_CTX), 1 }; /* {{{ PHP_RIPEMD128Init * ripemd128 initialization. Begins a ripemd128 operation, writing a new context. */ PHP_HASH_API void PHP_RIPEMD128Init(PHP_RIPEMD128_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args) { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; } /* }}} */ /* {{{ PHP_RIPEMD256Init * ripemd256 initialization. Begins a ripemd256 operation, writing a new context. */ PHP_HASH_API void PHP_RIPEMD256Init(PHP_RIPEMD256_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args) { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0x76543210; context->state[5] = 0xFEDCBA98; context->state[6] = 0x89ABCDEF; context->state[7] = 0x01234567; } /* }}} */ /* {{{ PHP_RIPEMD160Init * ripemd160 initialization. Begins a ripemd160 operation, writing a new context. */ PHP_HASH_API void PHP_RIPEMD160Init(PHP_RIPEMD160_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args) { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; } /* }}} */ /* {{{ PHP_RIPEMD320Init * ripemd320 initialization. Begins a ripemd320 operation, writing a new context. */ PHP_HASH_API void PHP_RIPEMD320Init(PHP_RIPEMD320_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args) { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; context->state[5] = 0x76543210; context->state[6] = 0xFEDCBA98; context->state[7] = 0x89ABCDEF; context->state[8] = 0x01234567; context->state[9] = 0x3C2D1E0F; } /* }}} */ /* Basic ripemd function */ #define F0(x,y,z) ((x) ^ (y) ^ (z)) #define F1(x,y,z) (((x) & (y)) | ((~(x)) & (z))) #define F2(x,y,z) (((x) | (~(y))) ^ (z)) #define F3(x,y,z) (((x) & (z)) | ((y) & (~(z)))) #define F4(x,y,z) ((x) ^ ((y) | (~(z)))) static const uint32_t K_values[5] = { 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E }; /* 128, 256, 160, 320 */ static const uint32_t KK_values[4] = { 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x00000000 }; /* 128 & 256 */ static const uint32_t KK160_values[5] = { 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000 }; /* 160 & 320 */ #define K(n) K_values[ (n) >> 4] #define KK(n) KK_values[(n) >> 4] #define KK160(n) KK160_values[(n) >> 4] static const unsigned char R[80] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 }; static const unsigned char RR[80] = { 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 }; static const unsigned char S[80] = { 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 }; static const unsigned char SS[80] = { 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 }; #define ROLS(j, x) (((x) << S[j]) | ((x) >> (32 - S[j]))) #define ROLSS(j, x) (((x) << SS[j]) | ((x) >> (32 - SS[j]))) #define ROL(n, x) (((x) << n) | ((x) >> (32 - n))) /* {{{ RIPEMDDecode Decodes input (unsigned char) into output (uint32_t). Assumes len is a multiple of 4. */ static void RIPEMDDecode(uint32_t *output, const unsigned char *input, unsigned int len) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) output[i] = ((uint32_t) input[j + 0]) | (((uint32_t) input[j + 1]) << 8) | (((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24); } /* }}} */ /* {{{ RIPEMD128Transform * ripemd128 basic transformation. Transforms state based on block. */ static void RIPEMD128Transform(uint32_t state[4], const unsigned char block[64]) { uint32_t a = state[0], b = state[1], c = state[2], d = state[3]; uint32_t aa = state[0], bb = state[1], cc = state[2], dd = state[3]; uint32_t tmp, x[16]; int j; RIPEMDDecode(x, block, 64); for(j = 0; j < 16; j++) { tmp = ROLS( j, a + F0(b, c, d) + x[R[j]] + K(j)); a = d; d = c; c = b; b = tmp; tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK(j)); aa = dd; dd = cc; cc = bb; bb = tmp; } for(j = 16; j < 32; j++) { tmp = ROLS( j, a + F1(b, c, d) + x[R[j]] + K(j)); a = d; d = c; c = b; b = tmp; tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK(j)); aa = dd; dd = cc; cc = bb; bb = tmp; } for(j = 32; j < 48; j++) { tmp = ROLS( j, a + F2(b, c, d) + x[R[j]] + K(j)); a = d; d = c; c = b; b = tmp; tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK(j)); aa = dd; dd = cc; cc = bb; bb = tmp; } for(j = 48; j < 64; j++) { tmp = ROLS( j, a + F3(b, c, d) + x[R[j]] + K(j)); a = d; d = c; c = b; b = tmp; tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK(j)); aa = dd; dd = cc; cc = bb; bb = tmp; } tmp = state[1] + c + dd; state[1] = state[2] + d + aa; state[2] = state[3] + a + bb; state[3] = state[0] + b + cc; state[0] = tmp; tmp = 0; ZEND_SECURE_ZERO(x, sizeof(x)); } /* }}} */ /* {{{ PHP_RIPEMD128Update ripemd128 block update operation. Continues a ripemd128 message-digest operation, processing another message block, and updating the context. */ PHP_HASH_API void PHP_RIPEMD128Update(PHP_RIPEMD128_CTX * context, const unsigned char *input, size_t inputLen) { unsigned int i, index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) { context->count[1]++; } context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen); RIPEMD128Transform(context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) { RIPEMD128Transform(context->state, &input[i]); } index = 0; } else { i = 0; } /* Buffer remaining input */ memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i); } /* }}} */ /* {{{ RIPEMD256Transform * ripemd256 basic transformation. Transforms state based on block. */ static void RIPEMD256Transform(uint32_t state[8], const unsigned char block[64]) { uint32_t a = state[0], b = state[1], c = state[2], d = state[3]; uint32_t aa = state[4], bb = state[5], cc = state[6], dd = state[7]; uint32_t tmp, x[16]; int j; RIPEMDDecode(x, block, 64); for(j = 0; j < 16; j++) { tmp = ROLS( j, a + F0(b, c, d) + x[R[j]] + K(j)); a = d; d = c; c = b; b = tmp; tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK(j)); aa = dd; dd = cc; cc = bb; bb = tmp; } tmp = a; a = aa; aa = tmp; for(j = 16; j < 32; j++) { tmp = ROLS( j, a + F1(b, c, d) + x[R[j]] + K(j)); a = d; d = c; c = b; b = tmp; tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK(j)); aa = dd; dd = cc; cc = bb; bb = tmp; } tmp = b; b = bb; bb = tmp; for(j = 32; j < 48; j++) { tmp = ROLS( j, a + F2(b, c, d) + x[R[j]] + K(j)); a = d; d = c; c = b; b = tmp; tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK(j)); aa = dd; dd = cc; cc = bb; bb = tmp; } tmp = c; c = cc; cc = tmp; for(j = 48; j < 64; j++) { tmp = ROLS( j, a + F3(b, c, d) + x[R[j]] + K(j)); a = d; d = c; c = b; b = tmp; tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK(j)); aa = dd; dd = cc; cc = bb; bb = tmp; } tmp = d; d = dd; dd = tmp; state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += aa; state[5] += bb; state[6] += cc; state[7] += dd; tmp = 0; ZEND_SECURE_ZERO(x, sizeof(x)); } /* }}} */ /* {{{ PHP_RIPEMD256Update ripemd256 block update operation. Continues a ripemd256 message-digest operation, processing another message block, and updating the context. */ PHP_HASH_API void PHP_RIPEMD256Update(PHP_RIPEMD256_CTX * context, const unsigned char *input, size_t inputLen) { unsigned int i, index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) { context->count[1]++; } context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen); RIPEMD256Transform(context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) { RIPEMD256Transform(context->state, &input[i]); } index = 0; } else { i = 0; } /* Buffer remaining input */ memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i); } /* }}} */ /* {{{ RIPEMD160Transform * ripemd160 basic transformation. Transforms state based on block. */ static void RIPEMD160Transform(uint32_t state[5], const unsigned char block[64]) { uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; uint32_t aa = state[0], bb = state[1], cc = state[2], dd = state[3], ee = state[4]; uint32_t tmp, x[16]; int j; RIPEMDDecode(x, block, 64); for(j = 0; j < 16; j++) { tmp = ROLS( j, a + F0(b, c, d) + x[R[j]] + K(j)) + e; a = e; e = d; d = ROL(10, c); c = b; b = tmp; tmp = ROLSS(j, aa + F4(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee; aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp; } for(j = 16; j < 32; j++) { tmp = ROLS( j, a + F1(b, c, d) + x[R[j]] + K(j)) + e; a = e; e = d; d = ROL(10, c); c = b; b = tmp; tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee; aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp; } for(j = 32; j < 48; j++) { tmp = ROLS( j, a + F2(b, c, d) + x[R[j]] + K(j)) + e; a = e; e = d; d = ROL(10, c); c = b; b = tmp; tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee; aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp; } for(j = 48; j < 64; j++) { tmp = ROLS( j, a + F3(b, c, d) + x[R[j]] + K(j)) + e; a = e; e = d; d = ROL(10, c); c = b; b = tmp; tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee; aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp; } for(j = 64; j < 80; j++) { tmp = ROLS( j, a + F4(b, c, d) + x[R[j]] + K(j)) + e; a = e; e = d; d = ROL(10, c); c = b; b = tmp; tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee; aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp; } tmp = state[1] + c + dd; state[1] = state[2] + d + ee; state[2] = state[3] + e + aa; state[3] = state[4] + a + bb; state[4] = state[0] + b + cc; state[0] = tmp; tmp = 0; ZEND_SECURE_ZERO(x, sizeof(x)); } /* }}} */ /* {{{ PHP_RIPEMD160Update ripemd160 block update operation. Continues a ripemd160 message-digest operation, processing another message block, and updating the context. */ PHP_HASH_API void PHP_RIPEMD160Update(PHP_RIPEMD160_CTX * context, const unsigned char *input, size_t inputLen) { unsigned int i, index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) { context->count[1]++; } context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen); RIPEMD160Transform(context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) { RIPEMD160Transform(context->state, &input[i]); } index = 0; } else { i = 0; } /* Buffer remaining input */ memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i); } /* }}} */ /* {{{ RIPEMD320Transform * ripemd320 basic transformation. Transforms state based on block. */ static void RIPEMD320Transform(uint32_t state[10], const unsigned char block[64]) { uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; uint32_t aa = state[5], bb = state[6], cc = state[7], dd = state[8], ee = state[9]; uint32_t tmp, x[16]; int j; RIPEMDDecode(x, block, 64); for(j = 0; j < 16; j++) { tmp = ROLS( j, a + F0(b, c, d) + x[R[j]] + K(j)) + e; a = e; e = d; d = ROL(10, c); c = b; b = tmp; tmp = ROLSS(j, aa + F4(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee; aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp; } tmp = b; b = bb; bb = tmp; for(j = 16; j < 32; j++) { tmp = ROLS( j, a + F1(b, c, d) + x[R[j]] + K(j)) + e; a = e; e = d; d = ROL(10, c); c = b; b = tmp; tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee; aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp; } tmp = d; d = dd; dd = tmp; for(j = 32; j < 48; j++) { tmp = ROLS( j, a + F2(b, c, d) + x[R[j]] + K(j)) + e; a = e; e = d; d = ROL(10, c); c = b; b = tmp; tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee; aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp; } tmp = a; a = aa; aa = tmp; for(j = 48; j < 64; j++) { tmp = ROLS( j, a + F3(b, c, d) + x[R[j]] + K(j)) + e; a = e; e = d; d = ROL(10, c); c = b; b = tmp; tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee; aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp; } tmp = c; c = cc; cc = tmp; for(j = 64; j < 80; j++) { tmp = ROLS( j, a + F4(b, c, d) + x[R[j]] + K(j)) + e; a = e; e = d; d = ROL(10, c); c = b; b = tmp; tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee; aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp; } tmp = e; e = ee; ee = tmp; state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += aa; state[6] += bb; state[7] += cc; state[8] += dd; state[9] += ee; tmp = 0; ZEND_SECURE_ZERO(x, sizeof(x)); } /* }}} */ /* {{{ PHP_RIPEMD320Update ripemd320 block update operation. Continues a ripemd320 message-digest operation, processing another message block, and updating the context. */ PHP_HASH_API void PHP_RIPEMD320Update(PHP_RIPEMD320_CTX * context, const unsigned char *input, size_t inputLen) { unsigned int i, index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) { context->count[1]++; } context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen); RIPEMD320Transform(context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) { RIPEMD320Transform(context->state, &input[i]); } index = 0; } else { i = 0; } /* Buffer remaining input */ memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i); } /* }}} */ static const unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* {{{ RIPEMDEncode Encodes input (uint32_t) into output (unsigned char). Assumes len is a multiple of 4. */ static void RIPEMDEncode(unsigned char *output, uint32_t *input, unsigned int len) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff); output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff); output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff); output[j + 0] = (unsigned char) (input[i] & 0xff); } } /* }}} */ /* {{{ PHP_RIPEMD128Final ripemd128 finalization. Ends a ripemd128 message-digest operation, writing the the message digest and zeroizing the context. */ PHP_HASH_API void PHP_RIPEMD128Final(unsigned char digest[16], PHP_RIPEMD128_CTX * context) { unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ bits[0] = (unsigned char) (context->count[0] & 0xFF); bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF); bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF); bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF); bits[4] = (unsigned char) (context->count[1] & 0xFF); bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF); bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF); bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF); /* Pad out to 56 mod 64. */ index = (unsigned int) ((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); PHP_RIPEMD128Update(context, PADDING, padLen); /* Append length (before padding) */ PHP_RIPEMD128Update(context, bits, 8); /* Store state in digest */ RIPEMDEncode(digest, context->state, 16); /* Zeroize sensitive information. */ ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context)); } /* }}} */ /* {{{ PHP_RIPEMD256Final ripemd256 finalization. Ends a ripemd256 message-digest operation, writing the the message digest and zeroizing the context. */ PHP_HASH_API void PHP_RIPEMD256Final(unsigned char digest[32], PHP_RIPEMD256_CTX * context) { unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ bits[0] = (unsigned char) (context->count[0] & 0xFF); bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF); bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF); bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF); bits[4] = (unsigned char) (context->count[1] & 0xFF); bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF); bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF); bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF); /* Pad out to 56 mod 64. */ index = (unsigned int) ((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); PHP_RIPEMD256Update(context, PADDING, padLen); /* Append length (before padding) */ PHP_RIPEMD256Update(context, bits, 8); /* Store state in digest */ RIPEMDEncode(digest, context->state, 32); /* Zeroize sensitive information. */ ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context)); } /* }}} */ /* {{{ PHP_RIPEMD160Final ripemd160 finalization. Ends a ripemd160 message-digest operation, writing the the message digest and zeroizing the context. */ PHP_HASH_API void PHP_RIPEMD160Final(unsigned char digest[20], PHP_RIPEMD160_CTX * context) { unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ bits[0] = (unsigned char) (context->count[0] & 0xFF); bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF); bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF); bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF); bits[4] = (unsigned char) (context->count[1] & 0xFF); bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF); bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF); bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF); /* Pad out to 56 mod 64. */ index = (unsigned int) ((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); PHP_RIPEMD160Update(context, PADDING, padLen); /* Append length (before padding) */ PHP_RIPEMD160Update(context, bits, 8); /* Store state in digest */ RIPEMDEncode(digest, context->state, 20); /* Zeroize sensitive information. */ ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context)); } /* }}} */ /* {{{ PHP_RIPEMD320Final ripemd320 finalization. Ends a ripemd320 message-digest operation, writing the the message digest and zeroizing the context. */ PHP_HASH_API void PHP_RIPEMD320Final(unsigned char digest[40], PHP_RIPEMD320_CTX * context) { unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ bits[0] = (unsigned char) (context->count[0] & 0xFF); bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF); bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF); bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF); bits[4] = (unsigned char) (context->count[1] & 0xFF); bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF); bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF); bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF); /* Pad out to 56 mod 64. */ index = (unsigned int) ((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); PHP_RIPEMD320Update(context, PADDING, padLen); /* Append length (before padding) */ PHP_RIPEMD320Update(context, bits, 8); /* Store state in digest */ RIPEMDEncode(digest, context->state, 40); /* Zeroize sensitive information. */ ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context)); } /* }}} */