1/* 2 * Copyright (c) 1995 - 2003 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#define HC_DEPRECATED_CRYPTO 35 36#include "config.h" 37 38#include "otp_locl.h" 39 40#include "otp_md.h" 41#include "crypto-headers.h" 42 43/* 44 * Compress len bytes from md into key 45 */ 46 47static void 48compressmd (OtpKey key, unsigned char *md, size_t len) 49{ 50 u_char *p = key; 51 52 memset (p, 0, OTPKEYSIZE); 53 while(len) { 54 *p++ ^= *md++; 55 *p++ ^= *md++; 56 *p++ ^= *md++; 57 *p++ ^= *md++; 58 len -= 4; 59 if (p == key + OTPKEYSIZE) 60 p = key; 61 } 62} 63 64/* 65 * For histerical reasons, in the OTP definition it's said that 66 * the result from SHA must be stored in little-endian order. See 67 * draft-ietf-otp-01.txt. 68 */ 69 70static void 71little_endian(unsigned char *res, size_t len) 72{ 73 unsigned char t; 74 size_t i; 75 76 for (i = 0; i < len; i += 4) { 77 t = res[i + 0]; res[i + 0] = res[i + 3]; res[i + 3] = t; 78 t = res[i + 1]; res[i + 1] = res[i + 2]; res[i + 2] = t; 79 } 80} 81 82static int 83otp_md_init (OtpKey key, 84 const char *pwd, 85 const char *seed, 86 const EVP_MD *md, 87 int le, 88 unsigned char *res, 89 size_t ressz) 90{ 91 EVP_MD_CTX *ctx; 92 char *p; 93 int len; 94 95 ctx = EVP_MD_CTX_create(); 96 97 len = strlen(pwd) + strlen(seed); 98 p = malloc (len + 1); 99 if (p == NULL) 100 return -1; 101 strlcpy (p, seed, len + 1); 102 strlwr (p); 103 strlcat (p, pwd, len + 1); 104 105 EVP_DigestInit_ex(ctx, md, NULL); 106 EVP_DigestUpdate(ctx, p, len); 107 EVP_DigestFinal_ex(ctx, res, NULL); 108 109 EVP_MD_CTX_destroy(ctx); 110 111 if (le) 112 little_endian(res, ressz); 113 114 free (p); 115 compressmd (key, res, ressz); 116 return 0; 117} 118 119static int 120otp_md_next (OtpKey key, 121 const EVP_MD *md, 122 int le, 123 unsigned char *res, 124 size_t ressz) 125{ 126 EVP_MD_CTX *ctx; 127 128 ctx = EVP_MD_CTX_create(); 129 130 EVP_DigestInit_ex(ctx, md, NULL); 131 EVP_DigestUpdate(ctx, key, OTPKEYSIZE); 132 EVP_DigestFinal_ex(ctx, res, NULL); 133 134 EVP_MD_CTX_destroy(ctx); 135 136 if (le) 137 little_endian(res, ressz); 138 139 compressmd (key, res, ressz); 140 return 0; 141} 142 143static int 144otp_md_hash (const char *data, 145 size_t len, 146 const EVP_MD *md, 147 int le, 148 unsigned char *res, 149 size_t ressz) 150{ 151 EVP_MD_CTX *ctx; 152 ctx = EVP_MD_CTX_create(); 153 154 EVP_DigestInit_ex(ctx, md, NULL); 155 EVP_DigestUpdate(ctx, data, len); 156 EVP_DigestFinal_ex(ctx, res, NULL); 157 158 EVP_MD_CTX_destroy(ctx); 159 160 if (le) 161 little_endian(res, ressz); 162 163 return 0; 164} 165 166int 167otp_md4_init (OtpKey key, const char *pwd, const char *seed) 168{ 169 unsigned char res[16]; 170 return otp_md_init (key, pwd, seed, EVP_md4(), 0, res, sizeof(res)); 171} 172 173int 174otp_md4_hash (const char *data, 175 size_t len, 176 unsigned char *res) 177{ 178 return otp_md_hash (data, len, EVP_md4(), 0, res, 16); 179} 180 181int 182otp_md4_next (OtpKey key) 183{ 184 unsigned char res[16]; 185 return otp_md_next (key, EVP_md4(), 0, res, sizeof(res)); 186} 187 188 189int 190otp_md5_init (OtpKey key, const char *pwd, const char *seed) 191{ 192 unsigned char res[16]; 193 return otp_md_init (key, pwd, seed, EVP_md5(), 0, res, sizeof(res)); 194} 195 196int 197otp_md5_hash (const char *data, 198 size_t len, 199 unsigned char *res) 200{ 201 return otp_md_hash (data, len, EVP_md5(), 0, res, 16); 202} 203 204int 205otp_md5_next (OtpKey key) 206{ 207 unsigned char res[16]; 208 return otp_md_next (key, EVP_md5(), 0, res, sizeof(res)); 209} 210 211int 212otp_sha_init (OtpKey key, const char *pwd, const char *seed) 213{ 214 unsigned char res[20]; 215 return otp_md_init (key, pwd, seed, EVP_sha1(), 1, res, sizeof(res)); 216} 217 218int 219otp_sha_hash (const char *data, 220 size_t len, 221 unsigned char *res) 222{ 223 return otp_md_hash (data, len, EVP_sha1(), 1, res, 20); 224} 225 226int 227otp_sha_next (OtpKey key) 228{ 229 unsigned char res[20]; 230 return otp_md_next (key, EVP_sha1(), 1, res, sizeof(res)); 231} 232