1 /* zxid/zxcrypto.c - Glue for cryptographical functions 2 * Copyright (c) 2015-2016 Synergetics NV (sampo@synergetics.be), All Rights Reserved. 3 * Copyright (c) 2011 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved. 4 * Copyright (c) 2006-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved. 5 * Author: Sampo Kellomaki (sampo@iki.fi) 6 * This is confidential unpublished proprietary source code of the author. 7 * NO WARRANTY, not even implied warranties. Contains trade secrets. 8 * Distribution prohibited unless authorized in writing. 9 * Licensed under Apache License 2.0, see file COPYING. 10 * $Id: zxcrypto.c,v 1.10 2009-11-24 23:53:40 sampo Exp $ 11 * 12 * 7.10.2008, added documentation --Sampo 13 * 29.8.2009, added zxid_mk_self_signed_cert() --Sampo 14 * 12.12.2011, added HMAC SHA-256 as needed by JWT/JWS --Sampo 15 * 6.6.2015, added aes-256-gcm --Sampo 16 * 16.10.2015, upgraded sha256 support, eliminated MD5 from certs --Sampo 17 * 18 * See paper: Tibor Jager, Kenneth G. Paterson, Juraj Somorovsky: "One Bad Apple: Backwards Compatibility Attacks on State-of-the-Art Cryptography", 2013 http://www.nds.ruhr-uni-bochum.de/research/publications/backwards-compatibility/ /t/BackwardsCompatibilityAttacks.pdf 19 * 20 * http://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption 21 * https://www.openssl.org/docs/crypto/EVP_EncryptInit.html#gcm_and_ocb_modes 22 */ 23 24 #include "platform.h" /* needed on Win32 for snprintf() et al. */ 25 26 #include <zx/errmac.h> 27 #include <zx/zx.h> 28 #include <zx/zxid.h> 29 #include <zx/zxidutil.h> 30 #include <zx/c/zx-sa-data.h> 31 #include <string.h> 32 #include <sys/stat.h> /* umask(2) */ 33 34 #ifdef USE_OPENSSL 35 #include <openssl/evp.h> 36 #include <openssl/md5.h> 37 #include <openssl/sha.h> 38 #include <openssl/hmac.h> 39 #include <openssl/rand.h> 40 #include <openssl/x509.h> 41 #include <openssl/x509v3.h> 42 #include <openssl/rsa.h> 43 #include <openssl/pem.h> 44 #endif 45 46 /* Called by: zxid_mk_jwt x2 */ 47 char* zx_hmac_sha256(struct zx_ctx* c, int key_len, const char* key, int data_len, const char* data, char* md, int* md_len) { 48 return (char*)HMAC(EVP_sha256(), key, key_len, (unsigned char*)data, data_len, (unsigned char*)md, (unsigned int*)md_len); 49 } 50 51 #if 0 52 /* Called by: */ 53 struct zx_str* zx_hmac_sha1(struct zx_ctx* c, struct zx_str* key, struct zx_str* ss) { 54 HMAC(EVP_sha1(), key->s, key->len, ss->s, ss->len, md, mdlen); 55 56 EVP_CIPHER_CTX *ctx; 57 EVP_CIPHER *type = EVP_des_cbc(); 58 59 int EVP_SealInit(ctx, type, char **ek, int *ekl, char *iv, EVP_PKEY **pubk, int npubk); 60 int EVP_SealUpdate(ctx, unsigned char *out, int *outl, unsigned char *in, int inl); 61 int EVP_SealFinal(ctx, unsigned char *out, int *outl); 62 } 63 64 /* Following are macros in openssl headers so we need to define wrapper functions. */ 65 66 /* Called by: */ 67 int zx_EVP_CIPHER_key_length(const EVP_CIPHER* cipher) { return EVP_CIPHER_key_length(cipher); } 68 int zx_EVP_CIPHER_iv_length(const EVP_CIPHER* cipher) { return EVP_CIPHER_iv_length(cipher); } 69 int zx_EVP_CIPHER_block_size(const EVP_CIPHER* cipher) { return EVP_CIPHER_block_size(cipher); } 70 #endif 71 72 /*() Get certificate signature algorithm string. This reads the 73 * signature algorithm from certificate itself. 74 * Returns something like "SHA1" or "SHA256" or "" on error. 75 */ 76 77 /* Called by: */ 78 const char* zxid_get_cert_signature_algo(X509* cert) 79 { 80 if (!cert) 81 return ""; 82 return OBJ_nid2ln(OBJ_obj2nid(cert->sig_alg->algorithm)); 83 } 84 85 /*() zx_raw_digest2() computes a message digest over two items. The result 86 * is placed in buffer md, which must already be of length sufficient for 87 * the digest. md will not be nul terminated (and will usually have binary 88 * data). Possible algos: "SHA1", "SHA256", "SHA512", etc. 89 * zx_raw_raw_digest() expects an algorithm object instead of a string. 90 * Returns 0 on failure or length of the digest on success. */ 91 92 int zx_raw_raw_digest2(struct zx_ctx* c, char* md, const EVP_MD* evp_digest, int len, const char* s, int len2, const char* s2) 93 { 94 char* where = "a"; 95 EVP_MD_CTX* mdctx; 96 unsigned int mdlen; 97 mdctx = EVP_MD_CTX_create(); 98 99 if (!EVP_DigestInit_ex(mdctx, evp_digest, 0 /* engine */)) { 100 where = "EVP_DigestInit_ex()"; 101 goto sslerr; 102 } 103 104 if (len && s) { 105 if (!EVP_DigestUpdate(mdctx, s, len)) { 106 where = "EVP_DigestUpdate()"; 107 goto sslerr; 108 } 109 } 110 111 if (len2 && s2) { 112 if (!EVP_DigestUpdate(mdctx, s2, len2)) { 113 where = "EVP_DigestUpdate() 2"; 114 goto sslerr; 115 } 116 } 117 118 if(!EVP_DigestFinal_ex(mdctx, (unsigned char*)md, &mdlen)) { 119 where = "EVP_DigestFinal_ex()"; 120 goto sslerr; 121 } 122 EVP_MD_CTX_destroy(mdctx); 123 return mdlen; 124 125 sslerr: 126 zx_report_openssl_err(where); 127 EVP_MD_CTX_destroy(mdctx); 128 return 0; 129 } 130 131 int zx_raw_digest2(struct zx_ctx* c, char* md, const char* algo, int len, const char* s, int len2, const char* s2) 132 { 133 const EVP_MD* evp_digest; 134 OpenSSL_add_all_digests(); 135 evp_digest = EVP_get_digestbyname(algo); 136 return zx_raw_raw_digest2(c, md, evp_digest, len, s, len2, s2); 137 } 138 139 /*() zx_EVP_DecryptFinal_ex() is a drop-in replacement for OpenSSL EVP_DecryptFinal_ex. 140 * It performs XML Enc compatible padding check. See OpenSSL bug 1067 141 * http://rt.openssl.org/Ticket/Display.html?user=guest&;pass=guest&id=1067 */ 142 143 /* Called by: zx_raw_cipher */ 144 int zx_EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) { 145 int i,n; 146 unsigned int b; 147 148 *outl=0; 149 b=ctx->cipher->block_size; 150 if (b > 1) { 151 if (ctx->buf_len || !ctx->final_used) { 152 //EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,EVP_R_WRONG_FINAL_BLOCK_LENGTH); 153 return(0); 154 } 155 ASSERTOPI(b, <=, sizeof ctx->final); 156 n=ctx->final[b-1]; 157 if (n == 0 || n > (int)b) { 158 //EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,EVP_R_BAD_DECRYPT); 159 return(0); 160 } 161 162 /* The padding used in XML Enc does not follow RFC 1423 163 * and is not supported by OpenSSL. The last padding byte 164 * is checked, but all other padding bytes are ignored 165 * and trimmed. 166 * 167 * [XMLENC] D. Eastlake, ed., XML Encryption Syntax and 168 * Processing, W3C Recommendation 10. Dec. 2002, 169 * www.w3.org/TR/2002/REC-xmlenc-core-20021210">http://www.w3.org/TR/2002/REC-xmlenc-core-20021210 */ 170 if (ctx->final[b-1] != n) { 171 //EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,EVP_R_BAD_DECRYPT); 172 return(0); 173 } 174 n=ctx->cipher->block_size-n; 175 for (i=0; i<n; i++) 176 out[i]=ctx->final[i]; 177 *outl=n; 178 } else 179 *outl=0; 180 return 1; 181 } 182 183 //#define ZX_DEFAULT_IV "012345678901234567890123456789012345678901234567890123456789" /* 60 */ 184 #define ZX_DEFAULT_IV "ZX_DEFAULT_IV ZXID.ORG SAML 2.0 and Liberty ID-WSF by Sampo." /* 60 */ 185 186 /*() zx_raw_cipher() can encrypt and decrypt, based on encflag, using symmetic cipher algo. 187 * If encflag (==1) indicates encryption, the initialization vector will be prepended. */ 188 189 /* Called by: zxenc_symkey_dec x4, zxenc_symkey_enc, zxid_psobj_dec, zxid_psobj_enc */ 190 struct zx_str* zx_raw_cipher(struct zx_ctx* c, const char* algo, int encflag, struct zx_str* key, int len, const char* s, int iv_len, const char* iv) 191 { 192 const char* ivv; 193 char* where = "start"; 194 struct zx_str* out; 195 int outlen=0, tmplen, alloclen; 196 const EVP_CIPHER* evp_cipher; 197 EVP_CIPHER_CTX ctx; 198 OpenSSL_add_all_algorithms(); 199 if ((errmac_debug&ERRMAC_DEBUG_MASK) > 2) hexdmp("plain ", s, len, 256); 200 D("len=%d s=%p", len, s); 201 EVP_CIPHER_CTX_init(&ctx); 202 evp_cipher = EVP_get_cipherbyname(algo); 203 if (!evp_cipher) { 204 ERR("Cipher algo name(%s) not recognized by the crypto library (OpenSSL)", algo); 205 return 0; 206 } 207 208 tmplen = EVP_CIPHER_iv_length(evp_cipher); 209 if (tmplen) { 210 if (iv) { 211 if (iv_len != tmplen) { 212 ERR("iv len=%d does not match one required by cipher=%d", iv_len, tmplen); 213 goto clean; 214 } 215 ivv = iv; 216 } else { 217 iv_len = tmplen; 218 ivv = ZX_DEFAULT_IV; 219 ASSERTOPI(EVP_MAX_IV_LENGTH, <=, sizeof(ZX_DEFAULT_IV)); 220 } 221 if ((errmac_debug&ERRMAC_DEBUG_MASK) > 2) hexdmp("iv ", ivv, iv_len, 1024); 222 } else 223 ivv = 0; 224 if ((errmac_debug&ERRMAC_DEBUG_MASK) > 2) hexdmp("symkey ", key->s, key->len, 1024); 225 226 #if 0 227 alloclen = EVP_CIPHER_block_size(evp_cipher); 228 alloclen = len + alloclen + alloclen; /* bit pessimistic, but man EVP_CipherInit is ambiguous about the actual size needed. */ 229 #else 230 /* 20150606, it appears aes-256-gcm reports too short block size, thus we impose a minimum. */ 231 alloclen = EVP_CIPHER_block_size(evp_cipher); 232 D("block_size=%d", alloclen); 233 alloclen = MAX(alloclen, 256); 234 alloclen = len + alloclen + alloclen; /* bit pessimistic, but man EVP_CipherInit is ambiguous about the actual size needed. */ 235 #endif 236 if (encflag) 237 alloclen += iv_len; 238 239 out = zx_new_len_str(c, alloclen); 240 D("alloclen=%d iv_len=%d encflag=%d out=%p iv=%p", alloclen, iv_len, encflag, out, iv); 241 if (!out) goto clean; 242 if (encflag) 243 memcpy(out->s, ivv, iv_len); 244 else 245 iv_len = 0; /* When decrypting, the iv has already been stripped. */ 246 247 if (!EVP_CipherInit_ex(&ctx, evp_cipher, 0 /* engine */, (unsigned char*)key->s, (unsigned char*)ivv, encflag)) { 248 where = "EVP_CipherInit_ex()"; 249 goto sslerr; 250 } 251 252 if (!EVP_CIPHER_CTX_set_key_length(&ctx, key->len)) { 253 D("key->len=%d", key->len); 254 where = "wrong key length for algorithm (block ciphers only accept keys of determined length)"; 255 goto sslerr; 256 } 257 258 if (!EVP_CipherUpdate(&ctx, (unsigned char*)out->s + iv_len, &outlen, (unsigned char*)s, len)) { /* Actual crypto happens here */ 259 D("len=%d s=%p iv_len=%d outlen=%d out->s=%p", len, s, iv_len, outlen, out->s); 260 where = "EVP_CipherUpdate()"; 261 goto sslerr; 262 } 263 264 ASSERTOPI(outlen + iv_len, <=, alloclen); 265 266 #if 0 267 if(!EVP_CipherFinal_ex(&ctx, (unsigned char*)out->s + iv_len + outlen, &tmplen)) { /* Append final block */ 268 where = "EVP_CipherFinal_ex()"; 269 goto sslerr; 270 } 271 #else 272 /* Patch from Eric Rybski <rybskej@yahoo.com> */ 273 if (encflag) { 274 if(!EVP_CipherFinal_ex(&ctx, (unsigned char*)out->s + iv_len + outlen, &tmplen)) { /* Append final block */ 275 where = "EVP_CipherFinal_ex()"; 276 goto sslerr; 277 } 278 } else { 279 /* Perform our own padding check, as XML Enc is not guaranteed compatible 280 * with OpenSSL & RFC 1423. See OpenSSL bug 1067 281 * http://rt.openssl.org/Ticket/Display.html?user=guest&;pass=guest&id=1067 */ 282 EVP_CIPHER_CTX_set_padding(&ctx, 0); 283 if(!zx_EVP_DecryptFinal_ex(&ctx, (unsigned char*)out->s + iv_len + outlen, &tmplen)) { /* Append final block */ 284 where = "zx_EVP_DecryptFinal_ex()"; 285 goto sslerr; 286 } 287 } 288 #endif 289 EVP_CIPHER_CTX_cleanup(&ctx); 290 291 outlen += tmplen; 292 ASSERTOPI(outlen + iv_len, <=, alloclen); 293 out->len = outlen + iv_len; 294 out->s[outlen + iv_len] = 0; /* nul term */ 295 if ((errmac_debug&ERRMAC_DEBUG_MASK) > 2) hexdmp("cipher ", out->s, out->len, 256); 296 return out; 297 298 sslerr: 299 D("where(%s)", where); 300 zx_report_openssl_err(where); 301 clean: 302 EVP_CIPHER_CTX_cleanup(&ctx); 303 return 0; 304 } 305 306 /*() RSA public key encryption. See zx_get_rsa_pub_from_cert() for 307 * a way to obtain public key data structure. 308 * N.B. This function +only+ does the public key part. It does not 309 * perform combined enc-session-key-with-pub-key-and-then-data-with-session-key 310 * operation, though this function could be used as a component to implement 311 * such a system. 312 * 313 * This is considered a low level function. See zxenc_pubkey_enc() for a higher level solution. */ 314 315 /* Called by: zxenc_pubkey_enc x2 */ 316 struct zx_str* zx_rsa_pub_enc(struct zx_ctx* c, struct zx_str* plain, RSA* rsa_pkey, int pad) 317 { 318 struct zx_str* ciphered; 319 int ret, siz = RSA_size(rsa_pkey); 320 321 if ((errmac_debug&ERRMAC_DEBUG_MASK) > 2) { 322 D("pad=%d, RSA public key follows...", pad); 323 RSA_print_fp(ERRMAC_DEBUG_LOG, rsa_pkey, 0); 324 } 325 326 switch (pad) { 327 case RSA_PKCS1_PADDING: 328 case RSA_SSLV23_PADDING: 329 if (plain->len > (siz-11)) 330 ERR("Too much data for RSA key: can=%d, you have %d bytes.\n", siz-11, plain->len); 331 WARN("RSA_PKCS1_PADDING %d v1.5: WARNING: This padding is vulnearable to attacks. Use OAEP instead.", pad); 332 /* See paper: Tibor Jager, Kenneth G. Paterson, Juraj Somorovsky: "One Bad Apple: Backwards Compatibility Attacks on State-of-the-Art Cryptography", 2013 http://www.nds.ruhr-uni-bochum.de/research/publications/backwards-compatibility/ /t/BackwardsCompatibilityAttacks.pdf */ 333 break; 334 case RSA_NO_PADDING: 335 if (plain->len > siz) 336 ERR("Too much data for RSA key: can=%d, you have %d bytes.\n", siz, plain->len); 337 break; 338 case RSA_PKCS1_OAEP_PADDING: 339 if (plain->len > (siz-41)) 340 ERR("Too much data for RSA key: can=%d, you have %d bytes.\n", siz-41, plain->len); 341 break; 342 default: D("Illegal padding(%d). See `man 3 rsa'\n",pad); 343 } 344 345 ciphered = zx_new_len_str(c, siz); 346 if (!ciphered) 347 return 0; 348 ret = RSA_public_encrypt(plain->len, (unsigned char*)plain->s, (unsigned char*)ciphered->s, rsa_pkey, pad); 349 if (siz != ret) { 350 D("RSA pub enc wrong ret=%d siz=%d\n",ret,siz); 351 zx_report_openssl_err("zx_pub_encrypt_rsa fail (${ret})"); 352 return 0; 353 } 354 ASSERTOPI(ret, <=, siz); 355 ciphered->len = ret; 356 ciphered->s[ret] = 0; 357 return ciphered; 358 } 359 360 /*() RSA public key decryption. See zx_get_rsa_pub_from_cert() for 361 * a way to obtain public key data structure. */ 362 363 /* Called by: */ 364 struct zx_str* zx_rsa_pub_dec(struct zx_ctx* c, struct zx_str* ciphered, RSA* rsa_pkey, int pad) 365 { 366 struct zx_str* plain; 367 int ret, siz = RSA_size(rsa_pkey); 368 plain = zx_new_len_str(c, siz); 369 if (!plain) 370 return 0; 371 if ((errmac_debug&ERRMAC_DEBUG_MASK) > 2) { 372 D("pad=%d, RSA public key follows...", pad); 373 RSA_print_fp(ERRMAC_DEBUG_LOG, rsa_pkey, 0); 374 } 375 ret = RSA_public_decrypt(ciphered->len, (unsigned char*)ciphered->s, (unsigned char*)plain->s, rsa_pkey, pad); 376 if (ret == -1) { 377 D("RSA public decrypt failed ret=%d len_cipher_data=%d",ret,ciphered->len); 378 zx_report_openssl_err("zx_public_decrypt_rsa fail"); 379 return 0; 380 } 381 ASSERTOPI(ret, <=, siz); 382 plain->len = ret; 383 plain->s[ret] = 0; 384 return plain; 385 } 386 387 /*() RSA private key decryption. See zxid_read_private_key() and zxid_extract_private_key() 388 * for ways to read in the private key data structure. 389 * N.B. This function +only+ does the private key part. It does not 390 * perform combined dec-session-key-with-priv-key-and-then-data-with-session-key 391 * operation, though this function could be used as a component to implement 392 * such a system. 393 * 394 * This is considered a low level function. See zxenc_privkey_dec() for a higher level solution. */ 395 396 /* Called by: zxenc_privkey_dec x2 */ 397 struct zx_str* zx_rsa_priv_dec(struct zx_ctx* c, struct zx_str* ciphered, RSA* rsa_pkey, int pad) 398 { 399 struct zx_str* plain; 400 int ret, siz = RSA_size(rsa_pkey); 401 plain = zx_new_len_str(c, siz); 402 if (!plain) 403 return 0; 404 if ((errmac_debug&ERRMAC_DEBUG_MASK) > 2) { 405 D("pad=%d, RSA private key follows...", pad); 406 RSA_print_fp(ERRMAC_DEBUG_LOG, rsa_pkey, 0); 407 } 408 ret = RSA_private_decrypt(ciphered->len, (unsigned char*)ciphered->s, (unsigned char*)plain->s, rsa_pkey, pad); 409 if (ret == -1) { 410 D("RSA private decrypt failed ret=%d len_cipher_data=%d",ret,ciphered->len); 411 zx_report_openssl_err("zx_priv_decrypt_rsa fail"); 412 return 0; 413 } 414 ASSERTOPI(ret, <=, siz); 415 plain->len = ret; 416 plain->s[ret] = 0; 417 return plain; 418 } 419 420 /*() RSA private key encryption. See zxid_read_private_key() and zxid_extract_private_key() 421 * for ways to read in the private key data structure. */ 422 423 /* Called by: */ 424 struct zx_str* zx_rsa_priv_enc(struct zx_ctx* c, struct zx_str* plain, RSA* rsa_pkey, int pad) 425 { 426 struct zx_str* ciphered; 427 int ret, siz = RSA_size(rsa_pkey); 428 ciphered = zx_new_len_str(c, siz); 429 if (!ciphered) 430 return 0; 431 if ((errmac_debug&ERRMAC_DEBUG_MASK) > 2) { 432 D("pad=%d, RSA private key follows...", pad); 433 RSA_print_fp(ERRMAC_DEBUG_LOG, rsa_pkey, 0); 434 } 435 ret = RSA_private_encrypt(plain->len, (unsigned char*)plain->s, (unsigned char*)ciphered->s, rsa_pkey, pad); 436 if (ret == -1) { 437 D("RSA private encrypt failed ret=%d len_plain=%d", ret, plain->len); 438 zx_report_openssl_err("zx_priv_encrypt_rsa fail"); 439 return 0; 440 } 441 ASSERTOPI(ret, <=, siz); 442 ciphered->len = ret; 443 ciphered->s[ret] = 0; 444 return ciphered; 445 } 446 447 /*() Obtain RSA public key from X509 certificate. The certificate must have been 448 * previously read into a data structure. See zxid_read_cert() and zxid_extract_cert() */ 449 450 /* Called by: zxenc_pubkey_enc, zxlog_write_line */ 451 RSA* zx_get_rsa_pub_from_cert(X509* cert, char* logkey) 452 { 453 EVP_PKEY* evp_pkey; 454 struct rsa_st* rsa_pkey; 455 evp_pkey = X509_get_pubkey(cert); 456 if (!evp_pkey) { 457 ERR("RSA enc: failed to get public key from certificate (perhaps you have not supplied any certificate, or it is corrupt or of wrong type) %s", logkey); 458 zx_report_openssl_err("zx_get_rsa_pub_from_cert"); 459 return 0; 460 } 461 rsa_pkey = EVP_PKEY_get1_RSA(evp_pkey); 462 if (!rsa_pkey) { 463 ERR("RSA enc: failed to extract RSA get public key from certificate (perhaps you have not supplied any certificate, or it is corrupt or of wrong type) %s", logkey); 464 zx_report_openssl_err("zx_get_rsa_pub_from_cert"); 465 return 0; 466 } 467 return rsa_pkey; 468 } 469 470 /*() ZXID centralized hook for obtaning random numbers. This backends to 471 * OpenSSL random number gnerator and seeds from /dev/urandom where 472 * available. If you want to use /dev/random, which may block, you need 473 * to recompile with ZXID_TRUE_RAND set to true. */ 474 475 /* Called by: */ 476 void zx_rand(char* buf, int n_bytes) 477 { 478 #ifdef USE_OPENSSL 479 #if ZXID_TRUE_RAND 480 RAND_bytes(buf, n_bytes); 481 #else 482 RAND_pseudo_bytes((unsigned char*)buf, n_bytes); 483 #endif 484 #else 485 ERR("ZXID was compiled without USE_OPENSSL. This means random number generation facilities are unavailable. Recompile ZXID or acknowledge that there is no security. n_rand_bytes=%d", n); 486 #endif 487 } 488 489 /* Called by: zxid_mk_at_cert x10, zxid_mk_self_sig_cert x7 */ 490 static void zxid_add_name_field(X509_NAME* subj, int typ, int nid, char* val) 491 { 492 X509_NAME_ENTRY* ne; 493 if (!val || !*val) 494 return; 495 ne = X509_NAME_ENTRY_create_by_NID(0, nid, typ, (unsigned char*)val, strlen(val)); 496 X509_NAME_add_entry(subj, ne, X509_NAME_entry_count(subj), 0); 497 } 498 499 /*() Create Self-Signed Certificate-Private Key pair and Certificate Signing Request 500 * This function is invoked when AUTO_CERT is set and a certificate is missing. 501 * As this is not expected to be frequent, we are cavalier about releasing 502 * the memory needed for each intermediate step. 503 * 504 * cf:: zxid configuration object, of which cf->ctx will be used for memory allocation 505 * buflen:: sizeof(buf) 506 * buf:: Buffer used for rendering pem representations of the certificate 507 * log key:: Who and why is calling 508 * name:: Name of the certificate file to be created 509 * returns:: 0 on failure, 1 on success 510 * 511 * See also: keygen() in keygen.c */ 512 513 /* Called by: */ 514 int zxid_mk_self_sig_cert(zxid_conf* cf, int buflen, char* buf, const char* lk, const char* name) 515 { 516 #ifdef USE_OPENSSL 517 BIO* wbio_cert; 518 BIO* wbio_pkey; 519 BIO* wbio_csr; 520 int len, lenq, um; 521 long cert_ser; 522 char* p; 523 char* q; 524 time_t ts; 525 X509* x509ss; 526 X509_REQ* req; 527 X509_REQ_INFO* ri; 528 EVP_PKEY* pkey; 529 EVP_PKEY* tmp_pkey; 530 RSA* rsa; 531 X509_EXTENSION* ext; 532 char cn[256]; 533 char ou[256]; 534 535 X509V3_add_standard_extensions(); 536 537 D("keygen start lk(%s) name(%s)", lk, name); 538 539 p = strstr(cf->burl, "://"); 540 if (p) { 541 p += sizeof("://")-1; 542 len = strcspn(p, ":/"); 543 if (len > sizeof(cn)-2) 544 len = sizeof(cn)-2; 545 memcpy(cn, p, len); 546 cn[len] = 0; 547 } else { 548 strcpy(cn, "Unknown server cn. Misconfiguration."); 549 } 550 551 #if 0 552 /* On some CAs the OU can not exceed 30 chars 2 3 553 * 123456789012345678901234567890 */ 554 snprintf(ou, sizeof(ou)-1, "SSO Dept ZXID Auto-Cert %s", cf->burl); 555 #else 556 snprintf(ou, sizeof(ou)-1, "SSO Dept ZXID Auto-Cert"); 557 #endif 558 ou[sizeof(ou)-1] = 0; /* must terminate manually as on win32 termination is not guaranteed */ 559 560 ts = time(0); 561 RAND_seed(&ts,sizeof(ts)); 562 #ifdef WINDOWS 563 RAND_screen(); /* Loading video display memory into random state */ 564 #endif 565 566 /* Here's the beef: Generate keypair */ 567 568 pkey=EVP_PKEY_new(); 569 DD("keygen preparing rsa key %s", lk); 570 #if 0 571 rsa = RSA_generate_key(1024 /*bits*/, 0x10001 /*65537*/, 0 /*req_cb*/, 0 /*arg*/); 572 #else 573 /* Crypto analysis (2015) suggests 1024bit key is too weak. */ 574 rsa = RSA_generate_key(2048 /*bits*/, 0x10001 /*65537*/, 0 /*req_cb*/, 0 /*arg*/); 575 #endif 576 DD("keygen rsa key generated %s", name); 577 EVP_PKEY_assign_RSA(pkey, rsa); 578 579 #if 0 580 /* Key generation is a big operation. Write in the new random state. */ 581 t = time(0); 582 RAND_seed(&t,sizeof(t)); 583 RAND_write_file(randomfile); 584 #endif 585 586 /* Now handle the public key part, i.e. create self signed and 587 * certificate request. This starts by making a request that 588 * contains all relevant fields. */ 589 590 req=X509_REQ_new(); 591 ri=req->req_info; 592 593 DD("keygen populate: set version %d (real vers is one higher)", 2); 594 ASN1_INTEGER_set(ri->version, 2L /* version 3 (binary value is one less) */); 595 596 #if 0 /* See cn code above */ 597 /* Parse domain name out of the URL: skip https:// and then scan name without port or path */ 598 599 for (p = cf->burl; !ONE_OF_2(*p, '/', 0); ++p) ; 600 if (*p != '/') goto badurl; 601 ++p; 602 if (*p != '/') { 603 badurl: 604 ERR("Malformed URL: does not start by https:// or http:// -- URL(%s)", cf->burl); 605 return 0; 606 } 607 ++p; 608 for (q = cn; !ONE_OF_3(*p, ':', '/', 0) && q < cn + sizeof(cn)-1; ++q, ++p) *q = *p; 609 *q = 0; 610 611 D("keygen populate DN: cn(%s) org(%s) c(%s) url=%p cn=%p p=%p q=%p", cn, cf->org_name, cf->country, cf->burl, cn, p, q); 612 #endif 613 614 /* Note on string types and allowable char sets: 615 * V_ASN1_PRINTABLESTRING [A-Za-z0-9 '()+,-./:=?] -- Any domain name, but not query string 616 * V_ASN1_IA5STRING Any 7bit string 617 * V_ASN1_T61STRING 8bit string */ 618 619 /* Construct DN part by part. We want cn=www.site.com,o=ZXID Auto-Cert */ 620 621 if (cf->contact_email) 622 zxid_add_name_field(ri->subject, V_ASN1_IA5STRING, NID_pkcs9_emailAddress, cf->contact_email); 623 zxid_add_name_field(ri->subject, V_ASN1_PRINTABLESTRING, NID_commonName, cn); 624 zxid_add_name_field(ri->subject, V_ASN1_T61STRING, NID_organizationalUnitName, ou); 625 zxid_add_name_field(ri->subject, V_ASN1_T61STRING, NID_organizationName, cf->org_name); 626 627 zxid_add_name_field(ri->subject, V_ASN1_T61STRING, NID_localityName, cf->locality); 628 zxid_add_name_field(ri->subject, V_ASN1_T61STRING, NID_stateOrProvinceName, cf->state); 629 zxid_add_name_field(ri->subject, V_ASN1_T61STRING, NID_countryName, cf->country); 630 631 #if 0 632 X509_ATTRIBUTE* xa; 633 ASN1_BIT_STRING* bs; 634 ASN1_TYPE* at; 635 636 /* It seems this gives indigestion to the default CA */ 637 DD("keygen populate attributes %s", lk); /* Add attributes: we really only need cn */ 638 639 xa = X509_ATTRIBUTE_new(); 640 xa->value.set = sk_ASN1_TYPE_new_null(); 641 /*xa->single = 1; **** this may also be set on some versions */ 642 xa->object=OBJ_nid2obj(NID_commonName); 643 644 bs = ASN1_BIT_STRING_new(); 645 bs->type = V_ASN1_PRINTABLESTRING; 646 ASN1_STRING_set(bs, cn, strlen(cn)+1); /* *** +1 why? Some archaic bug work-around? */ 647 648 at = ASN1_TYPE_new(); 649 ASN1_TYPE_set(at, bs->type, (char*)bs); 650 sk_ASN1_TYPE_push(xa->value.set, at); 651 sk_X509_ATTRIBUTE_push(ri->attributes, xa); 652 #endif 653 654 DD("keygen request populated %s", lk); 655 X509_REQ_set_pubkey(req, pkey); 656 /*req->req_info->req_kludge=0; / * no asn1 kludge *** filed deleted as of 0.9.7b?!? */ 657 658 DD("keygen signing request %s", lk); 659 #if 0 660 X509_REQ_sign(req, pkey, EVP_md5()); 661 #else 662 /* Due to recent (2013) progress in crypto analysis, MD5 and SHA1 are considered 663 * weak and support is likely to be discontinued in browsers and operating systems. */ 664 X509_REQ_sign(req, pkey, EVP_sha256()); 665 #endif 666 667 /* ----- X509 create self signed certificate ----- */ 668 669 DD("keygen making x509ss %s", lk); 670 x509ss = X509_new(); 671 X509_set_version(x509ss, 2); /* Set version to V3 and serial number to zero */ 672 zx_rand((char*)&cert_ser, 4); 673 ASN1_INTEGER_set(X509_get_serialNumber(x509ss), cert_ser); 674 DD("keygen setting various x509ss fields %s", lk); 675 676 X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)); 677 #if 1 678 ASN1_TIME_set(X509_get_notBefore(x509ss),0); 679 ASN1_TIME_set(X509_get_notAfter(x509ss), 0x7fffffffL); /* The end of the 32 bit Unix epoch */ 680 #else 681 X509_gmtime_adj(X509_get_notBefore(x509ss),0); 682 X509_gmtime_adj(X509_get_notAfter(x509ss), 0x7fffffffL); /* The end of the 32 bit Unix epoch */ 683 #endif 684 X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req)); 685 686 DD("keygen setting x509ss pubkey %s", lk); 687 tmp_pkey =X509_REQ_get_pubkey(req); 688 X509_set_pubkey(x509ss, tmp_pkey); 689 EVP_PKEY_free(tmp_pkey); 690 691 /* Set up V3 context struct and add certificate extensions. Note 692 * that we need to add (full) suite of CA extensions, otherwise 693 * our cert is not valid for signing itself. */ 694 695 ext = X509V3_EXT_conf_nid(0, 0, NID_basic_constraints, "CA:TRUE,pathlen:3"); 696 X509_add_ext(x509ss, ext, -1); 697 698 ext = X509V3_EXT_conf_nid(0, 0, NID_netscape_cert_type, "client,server,email,objsign,sslCA,emailCA,objCA"); 699 X509_add_ext(x509ss, ext, -1); 700 701 ext = X509V3_EXT_conf_nid(0, 0, NID_key_usage, "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign"); 702 X509_add_ext(x509ss, ext, -1); 703 704 ext = X509V3_EXT_conf_nid(0, 0, NID_netscape_comment, "Auto-Cert, see zxid.org"); 705 X509_add_ext(x509ss, ext, -1); 706 707 DD("keygen signing x509ss %s", lk); 708 #if 0 709 if (!(X509_sign(x509ss, pkey, EVP_md5()))) 710 #else 711 if (!(X509_sign(x509ss, pkey, EVP_sha256()))) 712 #endif 713 { 714 ERR("Failed to sign x509ss %s", lk); 715 zx_report_openssl_err("X509_sign"); 716 return 0; 717 } 718 DD("keygen x509ss ready %s", lk); 719 720 /* ----- Output phase ----- */ 721 722 um = umask(0077); /* Key material should be readable only by owner */ 723 724 wbio_csr = BIO_new(BIO_s_mem()); 725 DD("write_csr %s", lk); 726 if (!PEM_write_bio_X509_REQ(wbio_csr, req)) { 727 ERR("write_csr %s", lk); 728 zx_report_openssl_err("write_csr"); 729 return 0; 730 } 731 len = BIO_get_mem_data(wbio_csr, &p); 732 733 write_all_path("auto_cert csr", "%s" ZXID_PEM_DIR "csr-%s", cf->cpath, name, len, p); 734 BIO_free_all(wbio_csr); 735 736 /* Output combined self signed plus private key file. It is important 737 * that this happens after csr so that buf is left with this data 738 * so that the caller can then parse it. */ 739 740 wbio_cert = BIO_new(BIO_s_mem()); 741 DD("write_cert %s", lk); 742 if (!PEM_write_bio_X509(wbio_cert, x509ss)) { 743 ERR("write_cert %s", lk); 744 zx_report_openssl_err("write_cert"); 745 return 0; 746 } 747 len = BIO_get_mem_data(wbio_cert, &p); 748 749 wbio_pkey = BIO_new(BIO_s_mem()); 750 DD("write_private_key %s", lk); 751 if (!PEM_write_bio_PrivateKey(wbio_pkey, pkey, 0,0,0,0,0)) { 752 ERR("write_private_key %s", lk); 753 zx_report_openssl_err("write_private_key"); 754 return 0; 755 } 756 lenq = BIO_get_mem_data(wbio_pkey, &q); 757 758 write_all_path_fmt("auto_cert ss", buflen, buf, 759 "%s" ZXID_PEM_DIR "%s", cf->cpath, name, 760 "%.*s%.*s", len, p, lenq, q); 761 762 BIO_free_all(wbio_cert); 763 BIO_free_all(wbio_pkey); 764 765 umask(um); 766 767 EVP_PKEY_free(pkey); 768 X509_REQ_free(req); 769 X509_free(x509ss); 770 X509V3_EXT_cleanup(); 771 OBJ_cleanup(); 772 773 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, 0, "K", "KEYGEN", name, 0); 774 D("keygen done. %s", lk); 775 return 1; 776 #else 777 ERR("ZXID was compiled without USE_OPENSSL. This means self signed certificate generation facility is unavailable. Recompile ZXID. %s", lk); 778 return 0; 779 #endif 780 } 781 782 #if 0 783 /* use PEM_write_X509(fp, cert) instead! */ 784 /* Called by: */ 785 void zx_print_X509(FILE* fp, X509* cert) 786 { 787 int len; 788 char* p; 789 BIO* wbio_cert = BIO_new(BIO_s_mem()); 790 if (!PEM_write_bio_X509(wbio_cert, peer_cert)) { 791 ERR("write_cert %p", peer_cert); 792 zx_report_openssl_err("write_cert"); 793 return; 794 } 795 len = BIO_get_mem_data(wbio_cert, &p); 796 fprintf(fp, "%.*s", len, p); 797 } 798 #endif 799 800 /* 801 802 A Practical Approach of X.509 Attribute Certificate Framework as Support to Obtain Privilege Delegation 803 Jose A. Montenegro and Fernando Moya 804 Computer Science Department, E.T.S. Ingenieria Informatica, Universidad de Malage, Spain 805 Lecture Notes in Computer Science, 2004, Volume 3093/2004, 624, DOI: 10.1007/978-3-540-25980-0_13 806 807 Abstract This work introduces a particular implementation of the 808 X.509 Attribute Certificate framework (Xac), presented in the ITU-T 809 Recommendation. The implementation is based on the use of the Openssl 810 library, that we have chosen for its advantages in comparison with 811 other libraries. The paper also describes how the implementation is 812 middleware-oriented, focusing on the delegation model specified by 813 ITU-T proposal, and taking into consideration the ETSI report about 814 Xac. 815 816 RFC3281 817 http://tools.ietf.org/html/draft-ietf-pkix-3281update-05 818 819 */ 820 821 /*() Create X509 attribute certificate for one attribute and user specified by nameid (pseudonym) 822 * 823 * cf:: zxid configuration object, of which cf->ctx will be used for memory allocation 824 * buflen:: sizeof(buf) 825 * buf:: Buffer used for rendering pem representation of the certificate 826 * log key:: Who and why is calling 827 * nameid:: Name of the subject 828 * name:: Name of the attribute in certificate 829 * val:: Value of the attribute in certificate 830 * returns:: 0 on failure, 1 on success 831 */ 832 833 /* Called by: x509_test, zxid_map_val_ss */ 834 int zxid_mk_at_cert(zxid_conf* cf, int buflen, char* buf, const char* lk, zxid_nid* nameid, const char* name, struct zx_str* val) 835 { 836 #ifdef USE_OPENSSL 837 BIO* wbio_cert; 838 int len; 839 long cert_ser; 840 char* p; 841 time_t ts; 842 X509* x509ss; 843 X509_NAME* issuer; 844 X509_NAME* subject; 845 X509_EXTENSION* ext; 846 X509* sign_cert; 847 EVP_PKEY* sign_pkey; 848 char cn[256]; 849 char ou[256]; 850 851 X509V3_add_standard_extensions(); 852 853 D("keygen start lk(%s) name(%s)", lk, name); 854 855 p = strstr(cf->burl, "://"); 856 if (p) { 857 p += sizeof("://")-1; 858 len = strcspn(p, ":/"); 859 if (len > sizeof(cn)-2) 860 len = sizeof(cn)-2; 861 memcpy(cn, p, len); 862 cn[len] = 0; 863 } else { 864 strcpy(cn, "Unknown server cn. Misconfiguration."); 865 } 866 867 snprintf(ou, sizeof(ou)-1, "SSO Dept ZXID Auto-Cert %s", cf->burl); 868 ou[sizeof(ou)-1] = 0; /* must terminate manually as on win32 termination is not guaranteed */ 869 870 ts = time(0); 871 RAND_seed(&ts,sizeof(ts)); 872 #ifdef WINDOWS 873 RAND_screen(); /* Loading video display memory into random state */ 874 #endif 875 876 //ASN1_INTEGER_set(ri->version, 2L /* version 3 (binary value is one less) */); 877 878 /* Note on string types and allowable char sets: 879 * V_ASN1_PRINTABLESTRING [A-Za-z0-9 '()+,-./:=?] -- Any domain name, but not query string 880 * V_ASN1_IA5STRING Any 7bit string 881 * V_ASN1_T61STRING 8bit string */ 882 883 issuer = X509_NAME_new(); 884 subject = X509_NAME_new(); 885 886 /* Construct DN part by part. We want cn=www.site.com,o=ZXID Auto-Cert */ 887 888 zxid_add_name_field(issuer, V_ASN1_PRINTABLESTRING, NID_commonName, cn); 889 zxid_add_name_field(issuer, V_ASN1_T61STRING, NID_organizationalUnitName, ou); 890 zxid_add_name_field(issuer, V_ASN1_T61STRING, NID_organizationName, cf->org_name); 891 892 zxid_add_name_field(issuer, V_ASN1_T61STRING, NID_localityName, cf->locality); 893 zxid_add_name_field(issuer, V_ASN1_T61STRING, NID_stateOrProvinceName, cf->state); 894 zxid_add_name_field(issuer, V_ASN1_T61STRING, NID_countryName, cf->country); 895 896 /* Construct Subject part by part. */ 897 898 if (nameid) { 899 zxid_add_name_field(subject, V_ASN1_PRINTABLESTRING, NID_commonName, 900 zx_str_to_c(cf->ctx, ZX_GET_CONTENT(nameid))); 901 zxid_add_name_field(subject, V_ASN1_T61STRING, NID_organizationalUnitName, 902 zx_str_to_c(cf->ctx, &nameid->SPNameQualifier->g)); /* SP */ 903 zxid_add_name_field(subject, V_ASN1_T61STRING, NID_organizationName, 904 zx_str_to_c(cf->ctx, &nameid->NameQualifier->g)); /* IdP */ 905 } else { 906 zxid_add_name_field(subject, V_ASN1_PRINTABLESTRING, NID_commonName, "unspecified-see-zxid_mk_at_cert"); 907 } 908 909 /* ----- Create X509 certificate ----- */ 910 911 x509ss = X509_new(); 912 X509_set_version(x509ss, 2); /* Set version to V3 and serial number to zero */ 913 zx_rand((char*)&cert_ser, 4); 914 ASN1_INTEGER_set(X509_get_serialNumber(x509ss), cert_ser); 915 916 X509_set_issuer_name(x509ss, issuer); 917 #if 1 918 ASN1_TIME_set(X509_get_notBefore(x509ss),0); 919 ASN1_TIME_set(X509_get_notAfter(x509ss), 0x7fffffffL); /* The end of the 32 bit Unix epoch */ 920 #else 921 X509_gmtime_adj(X509_get_notBefore(x509ss),0); 922 X509_gmtime_adj(X509_get_notAfter(x509ss), 0x7fffffffL); /* The end of the 32 bit Unix epoch */ 923 #endif 924 X509_set_subject_name(x509ss, subject); 925 926 #if 0 /* *** schedule to remove */ 927 /* Set up V3 context struct and add certificate extensions. */ 928 929 ext = X509V3_EXT_conf_nid(0, 0, NID_basic_constraints, "CA:TRUE,pathlen:3"); 930 X509_add_ext(x509ss, ext, -1); 931 932 ext = X509V3_EXT_conf_nid(0, 0, NID_netscape_cert_type, "client,server,email,objsign,sslCA,emailCA,objCA"); 933 X509_add_ext(x509ss, ext, -1); 934 935 ext = X509V3_EXT_conf_nid(0, 0, NID_key_usage, "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign"); 936 X509_add_ext(x509ss, ext, -1); 937 #endif 938 939 ext = X509V3_EXT_conf_nid(0, 0, NID_netscape_comment, "Attribute cert, see zxid.org"); 940 X509_add_ext(x509ss, ext, -1); 941 942 #if 0 943 X509_ATTRIBUTE* xa; 944 ASN1_BIT_STRING* bs; 945 ASN1_TYPE* at; 946 947 /* It seems this gives indigestion to the default CA */ 948 DD("keygen populate attributes %s", lk); /* Add attributes: we really only need cn */ 949 950 xa = X509_ATTRIBUTE_new(); 951 xa->value.set = sk_ASN1_TYPE_new_null(); 952 /*xa->single = 1; **** this may also be set on some versions */ 953 xa->object=OBJ_nid2obj(NID_commonName); 954 955 bs = ASN1_BIT_STRING_new(); 956 bs->type = V_ASN1_PRINTABLESTRING; 957 ASN1_STRING_set(bs, cn, strlen(cn)+1); /* *** +1 why? Some archaic bug work-around? */ 958 959 at = ASN1_TYPE_new(); 960 ASN1_TYPE_set(at, bs->type, (char*)bs); 961 sk_ASN1_TYPE_push(xa->value.set, at); 962 sk_X509_ATTRIBUTE_push(ri->attributes, xa); 963 STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, X509_ATTRIBUTE *attr); 964 965 /* *** Exactly where on x509ss are the attributes supposed to attach?!? */ 966 #endif 967 968 zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "mk_at_cert"); 969 970 DD("keygen signing x509ss %s", lk); 971 #if 0 972 if (!(X509_sign(x509ss, sign_pkey, EVP_md5()))) 973 #else 974 if (!(X509_sign(x509ss, sign_pkey, EVP_sha256()))) 975 #endif 976 { 977 ERR("Failed to sign x509ss %s", lk); 978 zx_report_openssl_err("X509_sign"); 979 return 0; 980 } 981 DD("keygen x509ss ready %s", lk); 982 983 /* ----- Output phase ----- */ 984 985 wbio_cert = BIO_new(BIO_s_mem()); 986 DD("write_cert %s", lk); 987 if (!PEM_write_bio_X509(wbio_cert, x509ss)) { 988 ERR("write_cert %s", lk); 989 zx_report_openssl_err("write_cert"); 990 return 0; 991 } 992 len = BIO_get_mem_data(wbio_cert, &p); 993 memcpy(buf, p, MIN(len, buflen-1)); 994 buf[MIN(len, buflen-1)] = 0; 995 996 //***write_all_path("auto_cert ss", "%s" ZXID_PEM_DIR "%s", cf->cpath, name, len, p); 997 998 BIO_free_all(wbio_cert); 999 1000 X509_free(x509ss); 1001 X509V3_EXT_cleanup(); 1002 OBJ_cleanup(); 1003 1004 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, 0, "K", "X509ATCERT", name, 0); 1005 D("at cert done. %s", lk); 1006 return 1; 1007 #else 1008 ERR("ZXID was compiled without USE_OPENSSL. This means X509 attribute certificate generation facility is unavailable. Recompile ZXID. %s", lk); 1009 return 0; 1010 #endif 1011 } 1012 1013 /* Adapted by Sampo from FreeBSD md5_crypt.c, which is licensed as follows 1014 * ---------------------------------------------------------------------------- 1015 * "THE BEER-WARE LICENSE" (Revision 42): 1016 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you 1017 * can do whatever you want with this stuff. If we meet some day, and you think 1018 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 1019 * ---------------------------------------------------------------------------- 1020 */ 1021 1022 extern char pw_basis_64[64]; 1023 1024 /* Called by: add_password, zx_md5_crypt x6 */ 1025 static void to64(char *s, unsigned long v, int n) { 1026 while (--n >= 0) { 1027 *s++ = pw_basis_64[v & 0x3f]; 1028 v >>= 6; 1029 } 1030 } 1031 1032 /*() Compute MD5-Crypt password hash (starts by \$1\$) 1033 * 1034 * pw:: Password in plain 1035 * salt:: 0-8 chars of salt. Preceding \$1\$ is automatically skipped. Salt ends in \$ or nul. 1036 * buf:: must be at least 120 chars 1037 * return:: buf, nul terminated */ 1038 1039 /* Called by: authn_user, main, zx_pw_chk */ 1040 char* zx_md5_crypt(const char* pw, const char* salt, char* buf) 1041 { 1042 const char* magic = "$1$"; /* magic prefix to identify algo */ 1043 char* p; 1044 const char *sp, *ep; 1045 unsigned char final[16]; 1046 int sl, pl, i, j; 1047 MD5_CTX ctx, ctx1; 1048 unsigned long l; 1049 1050 /* Refine the Salt first */ 1051 sp = salt; 1052 1053 /* If it starts with the magic string, then skip that */ 1054 if (!strncmp(sp, magic, strlen(magic))) 1055 sp += strlen(magic); 1056 1057 /* It stops at the first '$', max 8 chars */ 1058 for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) ; 1059 sl = ep - sp; /* get the length of the true salt */ 1060 1061 MD5_Init(&ctx); 1062 MD5_Update(&ctx, (unsigned const char *)pw, strlen(pw)); /* pw 1st, as it's most unknown */ 1063 MD5_Update(&ctx, (unsigned const char *)magic, strlen(magic)); /* Then our magic string */ 1064 MD5_Update(&ctx, (unsigned const char *)sp, sl); /* Then the raw salt */ 1065 1066 /* Then just as many characters of the MD5(pw,salt,pw) */ 1067 MD5_Init(&ctx1); 1068 MD5_Update(&ctx1, (unsigned const char *)pw, strlen(pw)); 1069 MD5_Update(&ctx1, (unsigned const char *)sp, sl); 1070 MD5_Update(&ctx1, (unsigned const char *)pw, strlen(pw)); 1071 MD5_Final(final, &ctx1); 1072 for (pl = strlen(pw); pl > 0; pl -= 16) 1073 MD5_Update(&ctx, (unsigned const char *)final, pl>16 ? 16 : pl); 1074 1075 ZERO(final, sizeof(final)); /* Don't leave anything around in vm they could use. */ 1076 1077 /* Then something really weird... */ 1078 for (j = 0, i = strlen(pw); i; i >>= 1) 1079 if (i & 1) 1080 MD5_Update(&ctx, (unsigned const char *)final+j, 1); 1081 else 1082 MD5_Update(&ctx, (unsigned const char *)pw+j, 1); 1083 1084 strcpy(buf, magic); /* Start the output string */ 1085 strncat(buf, sp, sl); 1086 strcat(buf, "$"); 1087 1088 MD5_Final(final, &ctx); 1089 1090 /* and now, just to make sure things don't run too fast 1091 * On a 60 Mhz Pentium this takes 34 msec, so you would 1092 * need 30 seconds to build a 1000 entry dictionary... */ 1093 for (i = 0; i < 1000; i++) { 1094 MD5_Init(&ctx1); 1095 if (i & 1) 1096 MD5_Update(&ctx1, (unsigned const char *)pw, strlen(pw)); 1097 else 1098 MD5_Update(&ctx1, (unsigned const char *)final, 16); 1099 1100 if (i % 3) 1101 MD5_Update(&ctx1, (unsigned const char *)sp, sl); 1102 1103 if (i % 7) 1104 MD5_Update(&ctx1, (unsigned const char *)pw, strlen(pw)); 1105 1106 if (i & 1) 1107 MD5_Update(&ctx1, (unsigned const char *)final, 16); 1108 else 1109 MD5_Update(&ctx1, (unsigned const char *)pw, strlen(pw)); 1110 MD5_Final(final, &ctx1); 1111 } 1112 1113 p = buf + strlen(buf); 1114 1115 l = (final[0] << 16) | (final[6] << 8) | final[12]; to64(p, l, 4); p += 4; 1116 l = (final[1] << 16) | (final[7] << 8) | final[13]; to64(p, l, 4); p += 4; 1117 l = (final[2] << 16) | (final[8] << 8) | final[14]; to64(p, l, 4); p += 4; 1118 l = (final[3] << 16) | (final[9] << 8) | final[15]; to64(p, l, 4); p += 4; 1119 l = (final[4] << 16) | (final[10] << 8) | final[5]; to64(p, l, 4); p += 4; 1120 l = final[11]; to64(p, l, 2); p += 2; 1121 *p = '\0'; 1122 1123 ZERO(final, sizeof(final)); /* Don't leave anything around in vm they could use. */ 1124 return buf; 1125 } 1126 1127 /* EOF - zxcrypto.c */ 1128