1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251876Speter * contributor license agreements. See the NOTICE file distributed with 3251876Speter * this work for additional information regarding copyright ownership. 4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251876Speter * (the "License"); you may not use this file except in compliance with 6251876Speter * the License. You may obtain a copy of the License at 7251876Speter * 8251876Speter * http://www.apache.org/licenses/LICENSE-2.0 9251876Speter * 10251876Speter * Unless required by applicable law or agreed to in writing, software 11251876Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251876Speter * See the License for the specific language governing permissions and 14251876Speter * limitations under the License. 15251876Speter */ 16251876Speter 17251876Speter/* 18251876Speter * The exported function: 19251876Speter * 20251876Speter * apr_sha1_base64(const char *clear, int len, char *out); 21251876Speter * 22251876Speter * provides a means to SHA1 crypt/encode a plaintext password in 23251876Speter * a way which makes password files compatible with those commonly 24251876Speter * used in netscape web and ldap installations. It was put together 25251876Speter * by Clinton Wong <clintdw@netcom.com>, who also notes that: 26251876Speter * 27251876Speter * Note: SHA1 support is useful for migration purposes, but is less 28251876Speter * secure than Apache's password format, since Apache's (MD5) 29251876Speter * password format uses a random eight character salt to generate 30251876Speter * one of many possible hashes for the same password. Netscape 31251876Speter * uses plain SHA1 without a salt, so the same password 32251876Speter * will always generate the same hash, making it easier 33251876Speter * to break since the search space is smaller. 34251876Speter * 35251876Speter * See also the documentation in support/SHA1 as to hints on how to 36251876Speter * migrate an existing netscape installation and other supplied utitlites. 37251876Speter * 38251876Speter * This software also makes use of the following component: 39251876Speter * 40251876Speter * NIST Secure Hash Algorithm 41251876Speter * heavily modified by Uwe Hollerbach uh@alumni.caltech edu 42251876Speter * from Peter C. Gutmann's implementation as found in 43251876Speter * Applied Cryptography by Bruce Schneier 44251876Speter * This code is hereby placed in the public domain 45251876Speter */ 46251876Speter 47251876Speter#include "apr_sha1.h" 48251876Speter#include "apr_base64.h" 49251876Speter#include "apr_strings.h" 50251876Speter#include "apr_lib.h" 51251876Speter#if APR_CHARSET_EBCDIC 52251876Speter#include "apr_xlate.h" 53251876Speter#endif /*APR_CHARSET_EBCDIC*/ 54251876Speter#include <string.h> 55251876Speter 56251876Speter/* a bit faster & bigger, if defined */ 57251876Speter#define UNROLL_LOOPS 58251876Speter 59251876Speter/* NIST's proposed modification to SHA, 7/11/94 */ 60251876Speter#define USE_MODIFIED_SHA 61251876Speter 62251876Speter/* SHA f()-functions */ 63251876Speter#define f1(x,y,z) ((x & y) | (~x & z)) 64251876Speter#define f2(x,y,z) (x ^ y ^ z) 65251876Speter#define f3(x,y,z) ((x & y) | (x & z) | (y & z)) 66251876Speter#define f4(x,y,z) (x ^ y ^ z) 67251876Speter 68251876Speter/* SHA constants */ 69251876Speter#define CONST1 0x5a827999L 70251876Speter#define CONST2 0x6ed9eba1L 71251876Speter#define CONST3 0x8f1bbcdcL 72251876Speter#define CONST4 0xca62c1d6L 73251876Speter 74251876Speter/* 32-bit rotate */ 75251876Speter 76251876Speter#define ROT32(x,n) ((x << n) | (x >> (32 - n))) 77251876Speter 78251876Speter#define FUNC(n,i) \ 79251876Speter temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \ 80251876Speter E = D; D = C; C = ROT32(B,30); B = A; A = temp 81251876Speter 82251876Speter#define SHA_BLOCKSIZE 64 83251876Speter 84251876Speter#if APR_CHARSET_EBCDIC 85251876Speterstatic apr_xlate_t *ebcdic2ascii_xlate; 86251876Speter 87251876SpeterAPU_DECLARE(apr_status_t) apr_SHA1InitEBCDIC(apr_xlate_t *x) 88251876Speter{ 89251876Speter apr_status_t rv; 90251876Speter int onoff; 91251876Speter 92251876Speter /* Only single-byte conversion is supported. 93251876Speter */ 94251876Speter rv = apr_xlate_sb_get(x, &onoff); 95251876Speter if (rv) { 96251876Speter return rv; 97251876Speter } 98251876Speter if (!onoff) { /* If conversion is not single-byte-only */ 99251876Speter return APR_EINVAL; 100251876Speter } 101251876Speter ebcdic2ascii_xlate = x; 102251876Speter return APR_SUCCESS; 103251876Speter} 104251876Speter#endif 105251876Speter 106251876Speter/* do SHA transformation */ 107251876Speterstatic void sha_transform(apr_sha1_ctx_t *sha_info) 108251876Speter{ 109251876Speter int i; 110251876Speter apr_uint32_t temp, A, B, C, D, E, W[80]; 111251876Speter 112251876Speter for (i = 0; i < 16; ++i) { 113251876Speter W[i] = sha_info->data[i]; 114251876Speter } 115251876Speter for (i = 16; i < 80; ++i) { 116251876Speter W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]; 117251876Speter#ifdef USE_MODIFIED_SHA 118251876Speter W[i] = ROT32(W[i], 1); 119251876Speter#endif /* USE_MODIFIED_SHA */ 120251876Speter } 121251876Speter A = sha_info->digest[0]; 122251876Speter B = sha_info->digest[1]; 123251876Speter C = sha_info->digest[2]; 124251876Speter D = sha_info->digest[3]; 125251876Speter E = sha_info->digest[4]; 126251876Speter#ifdef UNROLL_LOOPS 127251876Speter FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4); 128251876Speter FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9); 129251876Speter FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14); 130251876Speter FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19); 131251876Speter 132251876Speter FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24); 133251876Speter FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29); 134251876Speter FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34); 135251876Speter FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39); 136251876Speter 137251876Speter FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44); 138251876Speter FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49); 139251876Speter FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54); 140251876Speter FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59); 141251876Speter 142251876Speter FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64); 143251876Speter FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69); 144251876Speter FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74); 145251876Speter FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79); 146251876Speter#else /* !UNROLL_LOOPS */ 147251876Speter for (i = 0; i < 20; ++i) { 148251876Speter FUNC(1,i); 149251876Speter } 150251876Speter for (i = 20; i < 40; ++i) { 151251876Speter FUNC(2,i); 152251876Speter } 153251876Speter for (i = 40; i < 60; ++i) { 154251876Speter FUNC(3,i); 155251876Speter } 156251876Speter for (i = 60; i < 80; ++i) { 157251876Speter FUNC(4,i); 158251876Speter } 159251876Speter#endif /* !UNROLL_LOOPS */ 160251876Speter sha_info->digest[0] += A; 161251876Speter sha_info->digest[1] += B; 162251876Speter sha_info->digest[2] += C; 163251876Speter sha_info->digest[3] += D; 164251876Speter sha_info->digest[4] += E; 165251876Speter} 166251876Speter 167251876Speterunion endianTest { 168251876Speter long Long; 169251876Speter char Char[sizeof(long)]; 170251876Speter}; 171251876Speter 172251876Speterstatic char isLittleEndian(void) 173251876Speter{ 174251876Speter static union endianTest u; 175251876Speter u.Long = 1; 176251876Speter return (u.Char[0] == 1); 177251876Speter} 178251876Speter 179251876Speter/* change endianness of data */ 180251876Speter 181251876Speter/* count is the number of bytes to do an endian flip */ 182251876Speterstatic void maybe_byte_reverse(apr_uint32_t *buffer, int count) 183251876Speter{ 184251876Speter int i; 185251876Speter apr_byte_t ct[4], *cp; 186251876Speter 187251876Speter if (isLittleEndian()) { /* do the swap only if it is little endian */ 188251876Speter count /= sizeof(apr_uint32_t); 189251876Speter cp = (apr_byte_t *) buffer; 190251876Speter for (i = 0; i < count; ++i) { 191251876Speter ct[0] = cp[0]; 192251876Speter ct[1] = cp[1]; 193251876Speter ct[2] = cp[2]; 194251876Speter ct[3] = cp[3]; 195251876Speter cp[0] = ct[3]; 196251876Speter cp[1] = ct[2]; 197251876Speter cp[2] = ct[1]; 198251876Speter cp[3] = ct[0]; 199251876Speter cp += sizeof(apr_uint32_t); 200251876Speter } 201251876Speter } 202251876Speter} 203251876Speter 204251876Speter/* initialize the SHA digest */ 205251876Speter 206251876SpeterAPU_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *sha_info) 207251876Speter{ 208251876Speter sha_info->digest[0] = 0x67452301L; 209251876Speter sha_info->digest[1] = 0xefcdab89L; 210251876Speter sha_info->digest[2] = 0x98badcfeL; 211251876Speter sha_info->digest[3] = 0x10325476L; 212251876Speter sha_info->digest[4] = 0xc3d2e1f0L; 213251876Speter sha_info->count_lo = 0L; 214251876Speter sha_info->count_hi = 0L; 215251876Speter sha_info->local = 0; 216251876Speter} 217251876Speter 218251876Speter/* update the SHA digest */ 219251876Speter 220251876SpeterAPU_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *sha_info, 221251876Speter const unsigned char *buffer, 222251876Speter unsigned int count) 223251876Speter{ 224251876Speter unsigned int i; 225251876Speter 226251876Speter if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) { 227251876Speter ++sha_info->count_hi; 228251876Speter } 229251876Speter sha_info->count_lo += (apr_uint32_t) count << 3; 230251876Speter sha_info->count_hi += (apr_uint32_t) count >> 29; 231251876Speter if (sha_info->local) { 232251876Speter i = SHA_BLOCKSIZE - sha_info->local; 233251876Speter if (i > count) { 234251876Speter i = count; 235251876Speter } 236251876Speter memcpy(((apr_byte_t *) sha_info->data) + sha_info->local, buffer, i); 237251876Speter count -= i; 238251876Speter buffer += i; 239251876Speter sha_info->local += i; 240251876Speter if (sha_info->local == SHA_BLOCKSIZE) { 241251876Speter maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); 242251876Speter sha_transform(sha_info); 243251876Speter } 244251876Speter else { 245251876Speter return; 246251876Speter } 247251876Speter } 248251876Speter while (count >= SHA_BLOCKSIZE) { 249251876Speter memcpy(sha_info->data, buffer, SHA_BLOCKSIZE); 250251876Speter buffer += SHA_BLOCKSIZE; 251251876Speter count -= SHA_BLOCKSIZE; 252251876Speter maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); 253251876Speter sha_transform(sha_info); 254251876Speter } 255251876Speter memcpy(sha_info->data, buffer, count); 256251876Speter sha_info->local = count; 257251876Speter} 258251876Speter 259251876SpeterAPU_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *sha_info, const char *buf, 260251876Speter unsigned int count) 261251876Speter{ 262251876Speter#if APR_CHARSET_EBCDIC 263251876Speter int i; 264251876Speter const apr_byte_t *buffer = (const apr_byte_t *) buf; 265251876Speter apr_size_t inbytes_left, outbytes_left; 266251876Speter 267251876Speter if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) { 268251876Speter ++sha_info->count_hi; 269251876Speter } 270251876Speter sha_info->count_lo += (apr_uint32_t) count << 3; 271251876Speter sha_info->count_hi += (apr_uint32_t) count >> 29; 272251876Speter /* Is there a remainder of the previous Update operation? */ 273251876Speter if (sha_info->local) { 274251876Speter i = SHA_BLOCKSIZE - sha_info->local; 275251876Speter if (i > count) { 276251876Speter i = count; 277251876Speter } 278251876Speter inbytes_left = outbytes_left = i; 279251876Speter apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left, 280251876Speter ((apr_byte_t *) sha_info->data) + sha_info->local, 281251876Speter &outbytes_left); 282251876Speter count -= i; 283251876Speter buffer += i; 284251876Speter sha_info->local += i; 285251876Speter if (sha_info->local == SHA_BLOCKSIZE) { 286251876Speter maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); 287251876Speter sha_transform(sha_info); 288251876Speter } 289251876Speter else { 290251876Speter return; 291251876Speter } 292251876Speter } 293251876Speter while (count >= SHA_BLOCKSIZE) { 294251876Speter inbytes_left = outbytes_left = SHA_BLOCKSIZE; 295251876Speter apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left, 296251876Speter (apr_byte_t *) sha_info->data, &outbytes_left); 297251876Speter buffer += SHA_BLOCKSIZE; 298251876Speter count -= SHA_BLOCKSIZE; 299251876Speter maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); 300251876Speter sha_transform(sha_info); 301251876Speter } 302251876Speter inbytes_left = outbytes_left = count; 303251876Speter apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left, 304251876Speter (apr_byte_t *) sha_info->data, &outbytes_left); 305251876Speter sha_info->local = count; 306251876Speter#else 307251876Speter apr_sha1_update_binary(sha_info, (const unsigned char *) buf, count); 308251876Speter#endif 309251876Speter} 310251876Speter 311251876Speter/* finish computing the SHA digest */ 312251876Speter 313251876SpeterAPU_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE], 314251876Speter apr_sha1_ctx_t *sha_info) 315251876Speter{ 316251876Speter int count, i, j; 317251876Speter apr_uint32_t lo_bit_count, hi_bit_count, k; 318251876Speter 319251876Speter lo_bit_count = sha_info->count_lo; 320251876Speter hi_bit_count = sha_info->count_hi; 321251876Speter count = (int) ((lo_bit_count >> 3) & 0x3f); 322251876Speter ((apr_byte_t *) sha_info->data)[count++] = 0x80; 323251876Speter if (count > SHA_BLOCKSIZE - 8) { 324251876Speter memset(((apr_byte_t *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count); 325251876Speter maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); 326251876Speter sha_transform(sha_info); 327251876Speter memset((apr_byte_t *) sha_info->data, 0, SHA_BLOCKSIZE - 8); 328251876Speter } 329251876Speter else { 330251876Speter memset(((apr_byte_t *) sha_info->data) + count, 0, 331251876Speter SHA_BLOCKSIZE - 8 - count); 332251876Speter } 333251876Speter maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); 334251876Speter sha_info->data[14] = hi_bit_count; 335251876Speter sha_info->data[15] = lo_bit_count; 336251876Speter sha_transform(sha_info); 337251876Speter 338251876Speter for (i = 0, j = 0; j < APR_SHA1_DIGESTSIZE; i++) { 339251876Speter k = sha_info->digest[i]; 340251876Speter digest[j++] = (unsigned char) ((k >> 24) & 0xff); 341251876Speter digest[j++] = (unsigned char) ((k >> 16) & 0xff); 342251876Speter digest[j++] = (unsigned char) ((k >> 8) & 0xff); 343251876Speter digest[j++] = (unsigned char) (k & 0xff); 344251876Speter } 345251876Speter} 346251876Speter 347251876Speter 348251876SpeterAPU_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out) 349251876Speter{ 350251876Speter int l; 351251876Speter apr_sha1_ctx_t context; 352251876Speter apr_byte_t digest[APR_SHA1_DIGESTSIZE]; 353251876Speter 354251876Speter apr_sha1_init(&context); 355251876Speter apr_sha1_update(&context, clear, len); 356251876Speter apr_sha1_final(digest, &context); 357251876Speter 358251876Speter /* private marker. */ 359251876Speter apr_cpystrn(out, APR_SHA1PW_ID, APR_SHA1PW_IDLEN + 1); 360251876Speter 361251876Speter /* SHA1 hash is always 20 chars */ 362251876Speter l = apr_base64_encode_binary(out + APR_SHA1PW_IDLEN, digest, sizeof(digest)); 363251876Speter out[l + APR_SHA1PW_IDLEN] = '\0'; 364251876Speter 365251876Speter /* 366251876Speter * output of base64 encoded SHA1 is always 28 chars + APR_SHA1PW_IDLEN 367251876Speter */ 368251876Speter} 369