1e71b7053SJung-uk Kim /* 2e71b7053SJung-uk Kim * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. 31f13597dSJung-uk Kim * 4e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 81f13597dSJung-uk Kim */ 91f13597dSJung-uk Kim 101f13597dSJung-uk Kim #include <stdio.h> 111f13597dSJung-uk Kim #include <string.h> 121f13597dSJung-uk Kim 131f13597dSJung-uk Kim #include <openssl/opensslconf.h> 141f13597dSJung-uk Kim #include <openssl/crypto.h> 151f13597dSJung-uk Kim #include <openssl/engine.h> 161f13597dSJung-uk Kim #include <openssl/evp.h> 171f13597dSJung-uk Kim #include <openssl/aes.h> 181f13597dSJung-uk Kim #include <openssl/rand.h> 191f13597dSJung-uk Kim #include <openssl/err.h> 20e71b7053SJung-uk Kim #include <openssl/modes.h> 211f13597dSJung-uk Kim 221f13597dSJung-uk Kim #ifndef OPENSSL_NO_HW 231f13597dSJung-uk Kim # ifndef OPENSSL_NO_HW_PADLOCK 241f13597dSJung-uk Kim 251f13597dSJung-uk Kim /* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */ 261f13597dSJung-uk Kim # if (OPENSSL_VERSION_NUMBER >= 0x00908000L) 271f13597dSJung-uk Kim # ifndef OPENSSL_NO_DYNAMIC_ENGINE 281f13597dSJung-uk Kim # define DYNAMIC_ENGINE 291f13597dSJung-uk Kim # endif 301f13597dSJung-uk Kim # elif (OPENSSL_VERSION_NUMBER >= 0x00907000L) 311f13597dSJung-uk Kim # ifdef ENGINE_DYNAMIC_SUPPORT 321f13597dSJung-uk Kim # define DYNAMIC_ENGINE 331f13597dSJung-uk Kim # endif 341f13597dSJung-uk Kim # else 351f13597dSJung-uk Kim # error "Only OpenSSL >= 0.9.7 is supported" 361f13597dSJung-uk Kim # endif 371f13597dSJung-uk Kim 386f9291ceSJung-uk Kim /* 396f9291ceSJung-uk Kim * VIA PadLock AES is available *ONLY* on some x86 CPUs. Not only that it 406f9291ceSJung-uk Kim * doesn't exist elsewhere, but it even can't be compiled on other platforms! 416f9291ceSJung-uk Kim */ 42e71b7053SJung-uk Kim 431f13597dSJung-uk Kim # undef COMPILE_HW_PADLOCK 44e71b7053SJung-uk Kim # if !defined(I386_ONLY) && defined(PADLOCK_ASM) 451f13597dSJung-uk Kim # define COMPILE_HW_PADLOCK 46e71b7053SJung-uk Kim # ifdef OPENSSL_NO_DYNAMIC_ENGINE 47e71b7053SJung-uk Kim static ENGINE *ENGINE_padlock(void); 481f13597dSJung-uk Kim # endif 491f13597dSJung-uk Kim # endif 501f13597dSJung-uk Kim 511f13597dSJung-uk Kim # ifdef OPENSSL_NO_DYNAMIC_ENGINE 52e71b7053SJung-uk Kim void engine_load_padlock_int(void); 53e71b7053SJung-uk Kim void engine_load_padlock_int(void) 541f13597dSJung-uk Kim { 551f13597dSJung-uk Kim /* On non-x86 CPUs it just returns. */ 561f13597dSJung-uk Kim # ifdef COMPILE_HW_PADLOCK 571f13597dSJung-uk Kim ENGINE *toadd = ENGINE_padlock(); 586f9291ceSJung-uk Kim if (!toadd) 596f9291ceSJung-uk Kim return; 601f13597dSJung-uk Kim ENGINE_add(toadd); 611f13597dSJung-uk Kim ENGINE_free(toadd); 621f13597dSJung-uk Kim ERR_clear_error(); 631f13597dSJung-uk Kim # endif 641f13597dSJung-uk Kim } 651f13597dSJung-uk Kim 661f13597dSJung-uk Kim # endif 671f13597dSJung-uk Kim 681f13597dSJung-uk Kim # ifdef COMPILE_HW_PADLOCK 691f13597dSJung-uk Kim 701f13597dSJung-uk Kim /* Function for ENGINE detection and control */ 711f13597dSJung-uk Kim static int padlock_available(void); 721f13597dSJung-uk Kim static int padlock_init(ENGINE *e); 731f13597dSJung-uk Kim 741f13597dSJung-uk Kim /* RNG Stuff */ 751f13597dSJung-uk Kim static RAND_METHOD padlock_rand; 761f13597dSJung-uk Kim 771f13597dSJung-uk Kim /* Cipher Stuff */ 786f9291ceSJung-uk Kim static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 796f9291ceSJung-uk Kim const int **nids, int nid); 801f13597dSJung-uk Kim 811f13597dSJung-uk Kim /* Engine names */ 821f13597dSJung-uk Kim static const char *padlock_id = "padlock"; 831f13597dSJung-uk Kim static char padlock_name[100]; 841f13597dSJung-uk Kim 851f13597dSJung-uk Kim /* Available features */ 861f13597dSJung-uk Kim static int padlock_use_ace = 0; /* Advanced Cryptography Engine */ 871f13597dSJung-uk Kim static int padlock_use_rng = 0; /* Random Number Generator */ 881f13597dSJung-uk Kim 891f13597dSJung-uk Kim /* ===== Engine "management" functions ===== */ 901f13597dSJung-uk Kim 911f13597dSJung-uk Kim /* Prepare the ENGINE structure for registration */ 926f9291ceSJung-uk Kim static int padlock_bind_helper(ENGINE *e) 931f13597dSJung-uk Kim { 941f13597dSJung-uk Kim /* Check available features */ 951f13597dSJung-uk Kim padlock_available(); 961f13597dSJung-uk Kim 97e71b7053SJung-uk Kim /* 98e71b7053SJung-uk Kim * RNG is currently disabled for reasons discussed in commentary just 99e71b7053SJung-uk Kim * before padlock_rand_bytes function. 100e71b7053SJung-uk Kim */ 1011f13597dSJung-uk Kim padlock_use_rng = 0; 1021f13597dSJung-uk Kim 1031f13597dSJung-uk Kim /* Generate a nice engine name with available features */ 1041f13597dSJung-uk Kim BIO_snprintf(padlock_name, sizeof(padlock_name), 1051f13597dSJung-uk Kim "VIA PadLock (%s, %s)", 1061f13597dSJung-uk Kim padlock_use_rng ? "RNG" : "no-RNG", 1071f13597dSJung-uk Kim padlock_use_ace ? "ACE" : "no-ACE"); 1081f13597dSJung-uk Kim 1091f13597dSJung-uk Kim /* Register everything or return with an error */ 1101f13597dSJung-uk Kim if (!ENGINE_set_id(e, padlock_id) || 1111f13597dSJung-uk Kim !ENGINE_set_name(e, padlock_name) || 1121f13597dSJung-uk Kim !ENGINE_set_init_function(e, padlock_init) || 1131f13597dSJung-uk Kim (padlock_use_ace && !ENGINE_set_ciphers(e, padlock_ciphers)) || 1141f13597dSJung-uk Kim (padlock_use_rng && !ENGINE_set_RAND(e, &padlock_rand))) { 1151f13597dSJung-uk Kim return 0; 1161f13597dSJung-uk Kim } 1171f13597dSJung-uk Kim 1181f13597dSJung-uk Kim /* Everything looks good */ 1191f13597dSJung-uk Kim return 1; 1201f13597dSJung-uk Kim } 1211f13597dSJung-uk Kim 1221f13597dSJung-uk Kim # ifdef OPENSSL_NO_DYNAMIC_ENGINE 1231f13597dSJung-uk Kim /* Constructor */ 1246f9291ceSJung-uk Kim static ENGINE *ENGINE_padlock(void) 1251f13597dSJung-uk Kim { 1261f13597dSJung-uk Kim ENGINE *eng = ENGINE_new(); 1271f13597dSJung-uk Kim 128e71b7053SJung-uk Kim if (eng == NULL) { 1291f13597dSJung-uk Kim return NULL; 1301f13597dSJung-uk Kim } 1311f13597dSJung-uk Kim 1321f13597dSJung-uk Kim if (!padlock_bind_helper(eng)) { 1331f13597dSJung-uk Kim ENGINE_free(eng); 1341f13597dSJung-uk Kim return NULL; 1351f13597dSJung-uk Kim } 1361f13597dSJung-uk Kim 1371f13597dSJung-uk Kim return eng; 1381f13597dSJung-uk Kim } 1391f13597dSJung-uk Kim # endif 1401f13597dSJung-uk Kim 1411f13597dSJung-uk Kim /* Check availability of the engine */ 1426f9291ceSJung-uk Kim static int padlock_init(ENGINE *e) 1431f13597dSJung-uk Kim { 1441f13597dSJung-uk Kim return (padlock_use_rng || padlock_use_ace); 1451f13597dSJung-uk Kim } 1461f13597dSJung-uk Kim 1476f9291ceSJung-uk Kim /* 1486f9291ceSJung-uk Kim * This stuff is needed if this ENGINE is being compiled into a 1496f9291ceSJung-uk Kim * self-contained shared-library. 1501f13597dSJung-uk Kim */ 1511f13597dSJung-uk Kim # ifdef DYNAMIC_ENGINE 1526f9291ceSJung-uk Kim static int padlock_bind_fn(ENGINE *e, const char *id) 1531f13597dSJung-uk Kim { 1541f13597dSJung-uk Kim if (id && (strcmp(id, padlock_id) != 0)) { 1551f13597dSJung-uk Kim return 0; 1561f13597dSJung-uk Kim } 1571f13597dSJung-uk Kim 1581f13597dSJung-uk Kim if (!padlock_bind_helper(e)) { 1591f13597dSJung-uk Kim return 0; 1601f13597dSJung-uk Kim } 1611f13597dSJung-uk Kim 1621f13597dSJung-uk Kim return 1; 1631f13597dSJung-uk Kim } 1641f13597dSJung-uk Kim 1651f13597dSJung-uk Kim IMPLEMENT_DYNAMIC_CHECK_FN() 1661f13597dSJung-uk Kim IMPLEMENT_DYNAMIC_BIND_FN(padlock_bind_fn) 1671f13597dSJung-uk Kim # endif /* DYNAMIC_ENGINE */ 1681f13597dSJung-uk Kim /* ===== Here comes the "real" engine ===== */ 169e71b7053SJung-uk Kim 1701f13597dSJung-uk Kim /* Some AES-related constants */ 1711f13597dSJung-uk Kim # define AES_BLOCK_SIZE 16 1721f13597dSJung-uk Kim # define AES_KEY_SIZE_128 16 1731f13597dSJung-uk Kim # define AES_KEY_SIZE_192 24 1741f13597dSJung-uk Kim # define AES_KEY_SIZE_256 32 1756f9291ceSJung-uk Kim /* 1766f9291ceSJung-uk Kim * Here we store the status information relevant to the current context. 1771f13597dSJung-uk Kim */ 1786f9291ceSJung-uk Kim /* 1796f9291ceSJung-uk Kim * BIG FAT WARNING: Inline assembler in PADLOCK_XCRYPT_ASM() depends on 1806f9291ceSJung-uk Kim * the order of items in this structure. Don't blindly modify, reorder, 1816f9291ceSJung-uk Kim * etc! 1826f9291ceSJung-uk Kim */ 1836f9291ceSJung-uk Kim struct padlock_cipher_data { 1841f13597dSJung-uk Kim unsigned char iv[AES_BLOCK_SIZE]; /* Initialization vector */ 1856f9291ceSJung-uk Kim union { 1866f9291ceSJung-uk Kim unsigned int pad[4]; 1871f13597dSJung-uk Kim struct { 1881f13597dSJung-uk Kim int rounds:4; 1891f13597dSJung-uk Kim int dgst:1; /* n/a in C3 */ 1901f13597dSJung-uk Kim int align:1; /* n/a in C3 */ 1911f13597dSJung-uk Kim int ciphr:1; /* n/a in C3 */ 1921f13597dSJung-uk Kim unsigned int keygen:1; 1931f13597dSJung-uk Kim int interm:1; 1941f13597dSJung-uk Kim unsigned int encdec:1; 1951f13597dSJung-uk Kim int ksize:2; 1961f13597dSJung-uk Kim } b; 1971f13597dSJung-uk Kim } cword; /* Control word */ 1981f13597dSJung-uk Kim AES_KEY ks; /* Encryption key */ 1991f13597dSJung-uk Kim }; 2001f13597dSJung-uk Kim 201e71b7053SJung-uk Kim /* Interface to assembler module */ 202e71b7053SJung-uk Kim unsigned int padlock_capability(void); 203e71b7053SJung-uk Kim void padlock_key_bswap(AES_KEY *key); 204e71b7053SJung-uk Kim void padlock_verify_context(struct padlock_cipher_data *ctx); 205e71b7053SJung-uk Kim void padlock_reload_key(void); 206e71b7053SJung-uk Kim void padlock_aes_block(void *out, const void *inp, 207e71b7053SJung-uk Kim struct padlock_cipher_data *ctx); 208e71b7053SJung-uk Kim int padlock_ecb_encrypt(void *out, const void *inp, 209e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, size_t len); 210e71b7053SJung-uk Kim int padlock_cbc_encrypt(void *out, const void *inp, 211e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, size_t len); 212e71b7053SJung-uk Kim int padlock_cfb_encrypt(void *out, const void *inp, 213e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, size_t len); 214e71b7053SJung-uk Kim int padlock_ofb_encrypt(void *out, const void *inp, 215e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, size_t len); 216e71b7053SJung-uk Kim int padlock_ctr32_encrypt(void *out, const void *inp, 217e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, size_t len); 218e71b7053SJung-uk Kim int padlock_xstore(void *out, int edx); 219e71b7053SJung-uk Kim void padlock_sha1_oneshot(void *ctx, const void *inp, size_t len); 220e71b7053SJung-uk Kim void padlock_sha1(void *ctx, const void *inp, size_t len); 221e71b7053SJung-uk Kim void padlock_sha256_oneshot(void *ctx, const void *inp, size_t len); 222e71b7053SJung-uk Kim void padlock_sha256(void *ctx, const void *inp, size_t len); 2231f13597dSJung-uk Kim 2246f9291ceSJung-uk Kim /* 2256f9291ceSJung-uk Kim * Load supported features of the CPU to see if the PadLock is available. 2266f9291ceSJung-uk Kim */ 2276f9291ceSJung-uk Kim static int padlock_available(void) 2281f13597dSJung-uk Kim { 229e71b7053SJung-uk Kim unsigned int edx = padlock_capability(); 2301f13597dSJung-uk Kim 2311f13597dSJung-uk Kim /* Fill up some flags */ 2321f13597dSJung-uk Kim padlock_use_ace = ((edx & (0x3 << 6)) == (0x3 << 6)); 2331f13597dSJung-uk Kim padlock_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2)); 2341f13597dSJung-uk Kim 2351f13597dSJung-uk Kim return padlock_use_ace + padlock_use_rng; 2361f13597dSJung-uk Kim } 2371f13597dSJung-uk Kim 2381f13597dSJung-uk Kim /* ===== AES encryption/decryption ===== */ 239e71b7053SJung-uk Kim 2401f13597dSJung-uk Kim # if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb) 2411f13597dSJung-uk Kim # define NID_aes_128_cfb NID_aes_128_cfb128 2421f13597dSJung-uk Kim # endif 243e71b7053SJung-uk Kim 2441f13597dSJung-uk Kim # if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb) 2451f13597dSJung-uk Kim # define NID_aes_128_ofb NID_aes_128_ofb128 2461f13597dSJung-uk Kim # endif 247e71b7053SJung-uk Kim 2481f13597dSJung-uk Kim # if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb) 2491f13597dSJung-uk Kim # define NID_aes_192_cfb NID_aes_192_cfb128 2501f13597dSJung-uk Kim # endif 251e71b7053SJung-uk Kim 2521f13597dSJung-uk Kim # if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb) 2531f13597dSJung-uk Kim # define NID_aes_192_ofb NID_aes_192_ofb128 2541f13597dSJung-uk Kim # endif 255e71b7053SJung-uk Kim 2561f13597dSJung-uk Kim # if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb) 2571f13597dSJung-uk Kim # define NID_aes_256_cfb NID_aes_256_cfb128 2581f13597dSJung-uk Kim # endif 259e71b7053SJung-uk Kim 2601f13597dSJung-uk Kim # if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb) 2611f13597dSJung-uk Kim # define NID_aes_256_ofb NID_aes_256_ofb128 2621f13597dSJung-uk Kim # endif 263e71b7053SJung-uk Kim 264e71b7053SJung-uk Kim /* List of supported ciphers. */ 265e71b7053SJung-uk Kim static const int padlock_cipher_nids[] = { 2661f13597dSJung-uk Kim NID_aes_128_ecb, 2671f13597dSJung-uk Kim NID_aes_128_cbc, 2681f13597dSJung-uk Kim NID_aes_128_cfb, 2691f13597dSJung-uk Kim NID_aes_128_ofb, 270e71b7053SJung-uk Kim NID_aes_128_ctr, 2711f13597dSJung-uk Kim 2721f13597dSJung-uk Kim NID_aes_192_ecb, 2731f13597dSJung-uk Kim NID_aes_192_cbc, 2741f13597dSJung-uk Kim NID_aes_192_cfb, 2751f13597dSJung-uk Kim NID_aes_192_ofb, 276e71b7053SJung-uk Kim NID_aes_192_ctr, 2771f13597dSJung-uk Kim 2781f13597dSJung-uk Kim NID_aes_256_ecb, 2791f13597dSJung-uk Kim NID_aes_256_cbc, 2801f13597dSJung-uk Kim NID_aes_256_cfb, 2811f13597dSJung-uk Kim NID_aes_256_ofb, 282e71b7053SJung-uk Kim NID_aes_256_ctr 2831f13597dSJung-uk Kim }; 2846f9291ceSJung-uk Kim 2851f13597dSJung-uk Kim static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids) / 2861f13597dSJung-uk Kim sizeof(padlock_cipher_nids[0])); 2871f13597dSJung-uk Kim 2881f13597dSJung-uk Kim /* Function prototypes ... */ 2891f13597dSJung-uk Kim static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 2901f13597dSJung-uk Kim const unsigned char *iv, int enc); 2911f13597dSJung-uk Kim 2921f13597dSJung-uk Kim # define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \ 2931f13597dSJung-uk Kim ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F ) ) 2941f13597dSJung-uk Kim # define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\ 295e71b7053SJung-uk Kim NEAREST_ALIGNED(EVP_CIPHER_CTX_get_cipher_data(ctx))) 296e71b7053SJung-uk Kim 297e71b7053SJung-uk Kim static int 298e71b7053SJung-uk Kim padlock_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, 299e71b7053SJung-uk Kim const unsigned char *in_arg, size_t nbytes) 300e71b7053SJung-uk Kim { 301e71b7053SJung-uk Kim return padlock_ecb_encrypt(out_arg, in_arg, 302e71b7053SJung-uk Kim ALIGNED_CIPHER_DATA(ctx), nbytes); 303e71b7053SJung-uk Kim } 304e71b7053SJung-uk Kim 305e71b7053SJung-uk Kim static int 306e71b7053SJung-uk Kim padlock_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, 307e71b7053SJung-uk Kim const unsigned char *in_arg, size_t nbytes) 308e71b7053SJung-uk Kim { 309e71b7053SJung-uk Kim struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); 310e71b7053SJung-uk Kim int ret; 311e71b7053SJung-uk Kim 312e71b7053SJung-uk Kim memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); 313e71b7053SJung-uk Kim if ((ret = padlock_cbc_encrypt(out_arg, in_arg, cdata, nbytes))) 314e71b7053SJung-uk Kim memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); 315e71b7053SJung-uk Kim return ret; 316e71b7053SJung-uk Kim } 317e71b7053SJung-uk Kim 318e71b7053SJung-uk Kim static int 319e71b7053SJung-uk Kim padlock_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, 320e71b7053SJung-uk Kim const unsigned char *in_arg, size_t nbytes) 321e71b7053SJung-uk Kim { 322e71b7053SJung-uk Kim struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); 323e71b7053SJung-uk Kim size_t chunk; 324e71b7053SJung-uk Kim 325e71b7053SJung-uk Kim if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */ 326e71b7053SJung-uk Kim unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx); 327e71b7053SJung-uk Kim 328e71b7053SJung-uk Kim if (chunk >= AES_BLOCK_SIZE) 329e71b7053SJung-uk Kim return 0; /* bogus value */ 330e71b7053SJung-uk Kim 331e71b7053SJung-uk Kim if (EVP_CIPHER_CTX_encrypting(ctx)) 332e71b7053SJung-uk Kim while (chunk < AES_BLOCK_SIZE && nbytes != 0) { 333e71b7053SJung-uk Kim ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk]; 334e71b7053SJung-uk Kim chunk++, nbytes--; 335e71b7053SJung-uk Kim } else 336e71b7053SJung-uk Kim while (chunk < AES_BLOCK_SIZE && nbytes != 0) { 337e71b7053SJung-uk Kim unsigned char c = *(in_arg++); 338e71b7053SJung-uk Kim *(out_arg++) = c ^ ivp[chunk]; 339e71b7053SJung-uk Kim ivp[chunk++] = c, nbytes--; 340e71b7053SJung-uk Kim } 341e71b7053SJung-uk Kim 342e71b7053SJung-uk Kim EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE); 343e71b7053SJung-uk Kim } 344e71b7053SJung-uk Kim 345e71b7053SJung-uk Kim if (nbytes == 0) 346e71b7053SJung-uk Kim return 1; 347e71b7053SJung-uk Kim 348e71b7053SJung-uk Kim memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); 349e71b7053SJung-uk Kim 350e71b7053SJung-uk Kim if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) { 351e71b7053SJung-uk Kim if (!padlock_cfb_encrypt(out_arg, in_arg, cdata, chunk)) 352e71b7053SJung-uk Kim return 0; 353e71b7053SJung-uk Kim nbytes -= chunk; 354e71b7053SJung-uk Kim } 355e71b7053SJung-uk Kim 356e71b7053SJung-uk Kim if (nbytes) { 357e71b7053SJung-uk Kim unsigned char *ivp = cdata->iv; 358e71b7053SJung-uk Kim 359e71b7053SJung-uk Kim out_arg += chunk; 360e71b7053SJung-uk Kim in_arg += chunk; 361e71b7053SJung-uk Kim EVP_CIPHER_CTX_set_num(ctx, nbytes); 362e71b7053SJung-uk Kim if (cdata->cword.b.encdec) { 363e71b7053SJung-uk Kim cdata->cword.b.encdec = 0; 364e71b7053SJung-uk Kim padlock_reload_key(); 365e71b7053SJung-uk Kim padlock_aes_block(ivp, ivp, cdata); 366e71b7053SJung-uk Kim cdata->cword.b.encdec = 1; 367e71b7053SJung-uk Kim padlock_reload_key(); 368e71b7053SJung-uk Kim while (nbytes) { 369e71b7053SJung-uk Kim unsigned char c = *(in_arg++); 370e71b7053SJung-uk Kim *(out_arg++) = c ^ *ivp; 371e71b7053SJung-uk Kim *(ivp++) = c, nbytes--; 372e71b7053SJung-uk Kim } 373e71b7053SJung-uk Kim } else { 374e71b7053SJung-uk Kim padlock_reload_key(); 375e71b7053SJung-uk Kim padlock_aes_block(ivp, ivp, cdata); 376e71b7053SJung-uk Kim padlock_reload_key(); 377e71b7053SJung-uk Kim while (nbytes) { 378e71b7053SJung-uk Kim *ivp = *(out_arg++) = *(in_arg++) ^ *ivp; 379e71b7053SJung-uk Kim ivp++, nbytes--; 380e71b7053SJung-uk Kim } 381e71b7053SJung-uk Kim } 382e71b7053SJung-uk Kim } 383e71b7053SJung-uk Kim 384e71b7053SJung-uk Kim memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); 385e71b7053SJung-uk Kim 386e71b7053SJung-uk Kim return 1; 387e71b7053SJung-uk Kim } 388e71b7053SJung-uk Kim 389e71b7053SJung-uk Kim static int 390e71b7053SJung-uk Kim padlock_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, 391e71b7053SJung-uk Kim const unsigned char *in_arg, size_t nbytes) 392e71b7053SJung-uk Kim { 393e71b7053SJung-uk Kim struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); 394e71b7053SJung-uk Kim size_t chunk; 395e71b7053SJung-uk Kim 396e71b7053SJung-uk Kim /* 397e71b7053SJung-uk Kim * ctx->num is maintained in byte-oriented modes, such as CFB and OFB... 398e71b7053SJung-uk Kim */ 399e71b7053SJung-uk Kim if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */ 400e71b7053SJung-uk Kim unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx); 401e71b7053SJung-uk Kim 402e71b7053SJung-uk Kim if (chunk >= AES_BLOCK_SIZE) 403e71b7053SJung-uk Kim return 0; /* bogus value */ 404e71b7053SJung-uk Kim 405e71b7053SJung-uk Kim while (chunk < AES_BLOCK_SIZE && nbytes != 0) { 406e71b7053SJung-uk Kim *(out_arg++) = *(in_arg++) ^ ivp[chunk]; 407e71b7053SJung-uk Kim chunk++, nbytes--; 408e71b7053SJung-uk Kim } 409e71b7053SJung-uk Kim 410e71b7053SJung-uk Kim EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE); 411e71b7053SJung-uk Kim } 412e71b7053SJung-uk Kim 413e71b7053SJung-uk Kim if (nbytes == 0) 414e71b7053SJung-uk Kim return 1; 415e71b7053SJung-uk Kim 416e71b7053SJung-uk Kim memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); 417e71b7053SJung-uk Kim 418e71b7053SJung-uk Kim if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) { 419e71b7053SJung-uk Kim if (!padlock_ofb_encrypt(out_arg, in_arg, cdata, chunk)) 420e71b7053SJung-uk Kim return 0; 421e71b7053SJung-uk Kim nbytes -= chunk; 422e71b7053SJung-uk Kim } 423e71b7053SJung-uk Kim 424e71b7053SJung-uk Kim if (nbytes) { 425e71b7053SJung-uk Kim unsigned char *ivp = cdata->iv; 426e71b7053SJung-uk Kim 427e71b7053SJung-uk Kim out_arg += chunk; 428e71b7053SJung-uk Kim in_arg += chunk; 429e71b7053SJung-uk Kim EVP_CIPHER_CTX_set_num(ctx, nbytes); 430e71b7053SJung-uk Kim padlock_reload_key(); /* empirically found */ 431e71b7053SJung-uk Kim padlock_aes_block(ivp, ivp, cdata); 432e71b7053SJung-uk Kim padlock_reload_key(); /* empirically found */ 433e71b7053SJung-uk Kim while (nbytes) { 434e71b7053SJung-uk Kim *(out_arg++) = *(in_arg++) ^ *ivp; 435e71b7053SJung-uk Kim ivp++, nbytes--; 436e71b7053SJung-uk Kim } 437e71b7053SJung-uk Kim } 438e71b7053SJung-uk Kim 439e71b7053SJung-uk Kim memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); 440e71b7053SJung-uk Kim 441e71b7053SJung-uk Kim return 1; 442e71b7053SJung-uk Kim } 443e71b7053SJung-uk Kim 444e71b7053SJung-uk Kim static void padlock_ctr32_encrypt_glue(const unsigned char *in, 445e71b7053SJung-uk Kim unsigned char *out, size_t blocks, 446e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, 447e71b7053SJung-uk Kim const unsigned char *ivec) 448e71b7053SJung-uk Kim { 449e71b7053SJung-uk Kim memcpy(ctx->iv, ivec, AES_BLOCK_SIZE); 450e71b7053SJung-uk Kim padlock_ctr32_encrypt(out, in, ctx, AES_BLOCK_SIZE * blocks); 451e71b7053SJung-uk Kim } 452e71b7053SJung-uk Kim 453e71b7053SJung-uk Kim static int 454e71b7053SJung-uk Kim padlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, 455e71b7053SJung-uk Kim const unsigned char *in_arg, size_t nbytes) 456e71b7053SJung-uk Kim { 457e71b7053SJung-uk Kim struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); 458e71b7053SJung-uk Kim unsigned int num = EVP_CIPHER_CTX_num(ctx); 459e71b7053SJung-uk Kim 460e71b7053SJung-uk Kim CRYPTO_ctr128_encrypt_ctr32(in_arg, out_arg, nbytes, 461e71b7053SJung-uk Kim cdata, EVP_CIPHER_CTX_iv_noconst(ctx), 462e71b7053SJung-uk Kim EVP_CIPHER_CTX_buf_noconst(ctx), &num, 463e71b7053SJung-uk Kim (ctr128_f) padlock_ctr32_encrypt_glue); 464e71b7053SJung-uk Kim 465e71b7053SJung-uk Kim EVP_CIPHER_CTX_set_num(ctx, (size_t)num); 466e71b7053SJung-uk Kim return 1; 467e71b7053SJung-uk Kim } 4681f13597dSJung-uk Kim 4691f13597dSJung-uk Kim # define EVP_CIPHER_block_size_ECB AES_BLOCK_SIZE 4701f13597dSJung-uk Kim # define EVP_CIPHER_block_size_CBC AES_BLOCK_SIZE 4711f13597dSJung-uk Kim # define EVP_CIPHER_block_size_OFB 1 4721f13597dSJung-uk Kim # define EVP_CIPHER_block_size_CFB 1 473e71b7053SJung-uk Kim # define EVP_CIPHER_block_size_CTR 1 4741f13597dSJung-uk Kim 4756f9291ceSJung-uk Kim /* 4766f9291ceSJung-uk Kim * Declaring so many ciphers by hand would be a pain. Instead introduce a bit 4776f9291ceSJung-uk Kim * of preprocessor magic :-) 4786f9291ceSJung-uk Kim */ 4791f13597dSJung-uk Kim # define DECLARE_AES_EVP(ksize,lmode,umode) \ 480e71b7053SJung-uk Kim static EVP_CIPHER *_hidden_aes_##ksize##_##lmode = NULL; \ 481e71b7053SJung-uk Kim static const EVP_CIPHER *padlock_aes_##ksize##_##lmode(void) \ 482e71b7053SJung-uk Kim { \ 483e71b7053SJung-uk Kim if (_hidden_aes_##ksize##_##lmode == NULL \ 484e71b7053SJung-uk Kim && ((_hidden_aes_##ksize##_##lmode = \ 485e71b7053SJung-uk Kim EVP_CIPHER_meth_new(NID_aes_##ksize##_##lmode, \ 4861f13597dSJung-uk Kim EVP_CIPHER_block_size_##umode, \ 487e71b7053SJung-uk Kim AES_KEY_SIZE_##ksize)) == NULL \ 488e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_##ksize##_##lmode, \ 489e71b7053SJung-uk Kim AES_BLOCK_SIZE) \ 490e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_flags(_hidden_aes_##ksize##_##lmode, \ 491e71b7053SJung-uk Kim 0 | EVP_CIPH_##umode##_MODE) \ 492e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_init(_hidden_aes_##ksize##_##lmode, \ 493e71b7053SJung-uk Kim padlock_aes_init_key) \ 494e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_##ksize##_##lmode, \ 495e71b7053SJung-uk Kim padlock_##lmode##_cipher) \ 496e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_##ksize##_##lmode, \ 497e71b7053SJung-uk Kim sizeof(struct padlock_cipher_data) + 16) \ 498e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_##ksize##_##lmode, \ 499e71b7053SJung-uk Kim EVP_CIPHER_set_asn1_iv) \ 500e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_##ksize##_##lmode, \ 501e71b7053SJung-uk Kim EVP_CIPHER_get_asn1_iv))) { \ 502e71b7053SJung-uk Kim EVP_CIPHER_meth_free(_hidden_aes_##ksize##_##lmode); \ 503e71b7053SJung-uk Kim _hidden_aes_##ksize##_##lmode = NULL; \ 504e71b7053SJung-uk Kim } \ 505e71b7053SJung-uk Kim return _hidden_aes_##ksize##_##lmode; \ 5061f13597dSJung-uk Kim } 5071f13597dSJung-uk Kim 508e71b7053SJung-uk Kim DECLARE_AES_EVP(128, ecb, ECB) 509e71b7053SJung-uk Kim DECLARE_AES_EVP(128, cbc, CBC) 510e71b7053SJung-uk Kim DECLARE_AES_EVP(128, cfb, CFB) 511e71b7053SJung-uk Kim DECLARE_AES_EVP(128, ofb, OFB) 512e71b7053SJung-uk Kim DECLARE_AES_EVP(128, ctr, CTR) 5131f13597dSJung-uk Kim 514e71b7053SJung-uk Kim DECLARE_AES_EVP(192, ecb, ECB) 515e71b7053SJung-uk Kim DECLARE_AES_EVP(192, cbc, CBC) 516e71b7053SJung-uk Kim DECLARE_AES_EVP(192, cfb, CFB) 517e71b7053SJung-uk Kim DECLARE_AES_EVP(192, ofb, OFB) 518e71b7053SJung-uk Kim DECLARE_AES_EVP(192, ctr, CTR) 5191f13597dSJung-uk Kim 520e71b7053SJung-uk Kim DECLARE_AES_EVP(256, ecb, ECB) 521e71b7053SJung-uk Kim DECLARE_AES_EVP(256, cbc, CBC) 522e71b7053SJung-uk Kim DECLARE_AES_EVP(256, cfb, CFB) 523e71b7053SJung-uk Kim DECLARE_AES_EVP(256, ofb, OFB) 524e71b7053SJung-uk Kim DECLARE_AES_EVP(256, ctr, CTR) 5251f13597dSJung-uk Kim 5261f13597dSJung-uk Kim static int 5276f9291ceSJung-uk Kim padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, 5286f9291ceSJung-uk Kim int nid) 5291f13597dSJung-uk Kim { 5301f13597dSJung-uk Kim /* No specific cipher => return a list of supported nids ... */ 5311f13597dSJung-uk Kim if (!cipher) { 5321f13597dSJung-uk Kim *nids = padlock_cipher_nids; 5331f13597dSJung-uk Kim return padlock_cipher_nids_num; 5341f13597dSJung-uk Kim } 5351f13597dSJung-uk Kim 5361f13597dSJung-uk Kim /* ... or the requested "cipher" otherwise */ 5371f13597dSJung-uk Kim switch (nid) { 5381f13597dSJung-uk Kim case NID_aes_128_ecb: 539e71b7053SJung-uk Kim *cipher = padlock_aes_128_ecb(); 5401f13597dSJung-uk Kim break; 5411f13597dSJung-uk Kim case NID_aes_128_cbc: 542e71b7053SJung-uk Kim *cipher = padlock_aes_128_cbc(); 5431f13597dSJung-uk Kim break; 5441f13597dSJung-uk Kim case NID_aes_128_cfb: 545e71b7053SJung-uk Kim *cipher = padlock_aes_128_cfb(); 5461f13597dSJung-uk Kim break; 5471f13597dSJung-uk Kim case NID_aes_128_ofb: 548e71b7053SJung-uk Kim *cipher = padlock_aes_128_ofb(); 549e71b7053SJung-uk Kim break; 550e71b7053SJung-uk Kim case NID_aes_128_ctr: 551e71b7053SJung-uk Kim *cipher = padlock_aes_128_ctr(); 5521f13597dSJung-uk Kim break; 5531f13597dSJung-uk Kim 5541f13597dSJung-uk Kim case NID_aes_192_ecb: 555e71b7053SJung-uk Kim *cipher = padlock_aes_192_ecb(); 5561f13597dSJung-uk Kim break; 5571f13597dSJung-uk Kim case NID_aes_192_cbc: 558e71b7053SJung-uk Kim *cipher = padlock_aes_192_cbc(); 5591f13597dSJung-uk Kim break; 5601f13597dSJung-uk Kim case NID_aes_192_cfb: 561e71b7053SJung-uk Kim *cipher = padlock_aes_192_cfb(); 5621f13597dSJung-uk Kim break; 5631f13597dSJung-uk Kim case NID_aes_192_ofb: 564e71b7053SJung-uk Kim *cipher = padlock_aes_192_ofb(); 565e71b7053SJung-uk Kim break; 566e71b7053SJung-uk Kim case NID_aes_192_ctr: 567e71b7053SJung-uk Kim *cipher = padlock_aes_192_ctr(); 5681f13597dSJung-uk Kim break; 5691f13597dSJung-uk Kim 5701f13597dSJung-uk Kim case NID_aes_256_ecb: 571e71b7053SJung-uk Kim *cipher = padlock_aes_256_ecb(); 5721f13597dSJung-uk Kim break; 5731f13597dSJung-uk Kim case NID_aes_256_cbc: 574e71b7053SJung-uk Kim *cipher = padlock_aes_256_cbc(); 5751f13597dSJung-uk Kim break; 5761f13597dSJung-uk Kim case NID_aes_256_cfb: 577e71b7053SJung-uk Kim *cipher = padlock_aes_256_cfb(); 5781f13597dSJung-uk Kim break; 5791f13597dSJung-uk Kim case NID_aes_256_ofb: 580e71b7053SJung-uk Kim *cipher = padlock_aes_256_ofb(); 581e71b7053SJung-uk Kim break; 582e71b7053SJung-uk Kim case NID_aes_256_ctr: 583e71b7053SJung-uk Kim *cipher = padlock_aes_256_ctr(); 5841f13597dSJung-uk Kim break; 5851f13597dSJung-uk Kim 5861f13597dSJung-uk Kim default: 5871f13597dSJung-uk Kim /* Sorry, we don't support this NID */ 5881f13597dSJung-uk Kim *cipher = NULL; 5891f13597dSJung-uk Kim return 0; 5901f13597dSJung-uk Kim } 5911f13597dSJung-uk Kim 5921f13597dSJung-uk Kim return 1; 5931f13597dSJung-uk Kim } 5941f13597dSJung-uk Kim 5951f13597dSJung-uk Kim /* Prepare the encryption key for PadLock usage */ 5961f13597dSJung-uk Kim static int 5971f13597dSJung-uk Kim padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 5981f13597dSJung-uk Kim const unsigned char *iv, int enc) 5991f13597dSJung-uk Kim { 6001f13597dSJung-uk Kim struct padlock_cipher_data *cdata; 6011f13597dSJung-uk Kim int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8; 602e71b7053SJung-uk Kim unsigned long mode = EVP_CIPHER_CTX_mode(ctx); 6031f13597dSJung-uk Kim 6046f9291ceSJung-uk Kim if (key == NULL) 6056f9291ceSJung-uk Kim return 0; /* ERROR */ 6061f13597dSJung-uk Kim 6071f13597dSJung-uk Kim cdata = ALIGNED_CIPHER_DATA(ctx); 608e71b7053SJung-uk Kim memset(cdata, 0, sizeof(*cdata)); 6091f13597dSJung-uk Kim 6101f13597dSJung-uk Kim /* Prepare Control word. */ 611e71b7053SJung-uk Kim if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE) 6121f13597dSJung-uk Kim cdata->cword.b.encdec = 0; 6131f13597dSJung-uk Kim else 614e71b7053SJung-uk Kim cdata->cword.b.encdec = (EVP_CIPHER_CTX_encrypting(ctx) == 0); 6151f13597dSJung-uk Kim cdata->cword.b.rounds = 10 + (key_len - 128) / 32; 6161f13597dSJung-uk Kim cdata->cword.b.ksize = (key_len - 128) / 64; 6171f13597dSJung-uk Kim 6181f13597dSJung-uk Kim switch (key_len) { 6191f13597dSJung-uk Kim case 128: 6206f9291ceSJung-uk Kim /* 6216f9291ceSJung-uk Kim * PadLock can generate an extended key for AES128 in hardware 6226f9291ceSJung-uk Kim */ 6231f13597dSJung-uk Kim memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128); 6241f13597dSJung-uk Kim cdata->cword.b.keygen = 0; 6251f13597dSJung-uk Kim break; 6261f13597dSJung-uk Kim 6271f13597dSJung-uk Kim case 192: 6281f13597dSJung-uk Kim case 256: 6296f9291ceSJung-uk Kim /* 6306f9291ceSJung-uk Kim * Generate an extended AES key in software. Needed for AES192/AES256 6316f9291ceSJung-uk Kim */ 6326f9291ceSJung-uk Kim /* 6336f9291ceSJung-uk Kim * Well, the above applies to Stepping 8 CPUs and is listed as 6346f9291ceSJung-uk Kim * hardware errata. They most likely will fix it at some point and 6356f9291ceSJung-uk Kim * then a check for stepping would be due here. 6366f9291ceSJung-uk Kim */ 637e71b7053SJung-uk Kim if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) 638e71b7053SJung-uk Kim && !enc) 6391f13597dSJung-uk Kim AES_set_decrypt_key(key, key_len, &cdata->ks); 640e71b7053SJung-uk Kim else 641e71b7053SJung-uk Kim AES_set_encrypt_key(key, key_len, &cdata->ks); 6421f13597dSJung-uk Kim # ifndef AES_ASM 6436f9291ceSJung-uk Kim /* 6446f9291ceSJung-uk Kim * OpenSSL C functions use byte-swapped extended key. 6456f9291ceSJung-uk Kim */ 646e71b7053SJung-uk Kim padlock_key_bswap(&cdata->ks); 6471f13597dSJung-uk Kim # endif 6481f13597dSJung-uk Kim cdata->cword.b.keygen = 1; 6491f13597dSJung-uk Kim break; 6501f13597dSJung-uk Kim 6511f13597dSJung-uk Kim default: 6521f13597dSJung-uk Kim /* ERROR */ 6531f13597dSJung-uk Kim return 0; 6541f13597dSJung-uk Kim } 6551f13597dSJung-uk Kim 6561f13597dSJung-uk Kim /* 6571f13597dSJung-uk Kim * This is done to cover for cases when user reuses the 6581f13597dSJung-uk Kim * context for new key. The catch is that if we don't do 6591f13597dSJung-uk Kim * this, padlock_eas_cipher might proceed with old key... 6601f13597dSJung-uk Kim */ 6611f13597dSJung-uk Kim padlock_reload_key(); 6621f13597dSJung-uk Kim 6631f13597dSJung-uk Kim return 1; 6641f13597dSJung-uk Kim } 6651f13597dSJung-uk Kim 6661f13597dSJung-uk Kim /* ===== Random Number Generator ===== */ 6671f13597dSJung-uk Kim /* 6681f13597dSJung-uk Kim * This code is not engaged. The reason is that it does not comply 6691f13597dSJung-uk Kim * with recommendations for VIA RNG usage for secure applications 6701f13597dSJung-uk Kim * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it 6711f13597dSJung-uk Kim * provide meaningful error control... 6721f13597dSJung-uk Kim */ 6736f9291ceSJung-uk Kim /* 6746f9291ceSJung-uk Kim * Wrapper that provides an interface between the API and the raw PadLock 6756f9291ceSJung-uk Kim * RNG 6766f9291ceSJung-uk Kim */ 6776f9291ceSJung-uk Kim static int padlock_rand_bytes(unsigned char *output, int count) 6781f13597dSJung-uk Kim { 6791f13597dSJung-uk Kim unsigned int eax, buf; 6801f13597dSJung-uk Kim 6811f13597dSJung-uk Kim while (count >= 8) { 6821f13597dSJung-uk Kim eax = padlock_xstore(output, 0); 6836f9291ceSJung-uk Kim if (!(eax & (1 << 6))) 6846f9291ceSJung-uk Kim return 0; /* RNG disabled */ 6851f13597dSJung-uk Kim /* this ---vv--- covers DC bias, Raw Bits and String Filter */ 6866f9291ceSJung-uk Kim if (eax & (0x1F << 10)) 6876f9291ceSJung-uk Kim return 0; 6886f9291ceSJung-uk Kim if ((eax & 0x1F) == 0) 6896f9291ceSJung-uk Kim continue; /* no data, retry... */ 6906f9291ceSJung-uk Kim if ((eax & 0x1F) != 8) 6916f9291ceSJung-uk Kim return 0; /* fatal failure... */ 6921f13597dSJung-uk Kim output += 8; 6931f13597dSJung-uk Kim count -= 8; 6941f13597dSJung-uk Kim } 6951f13597dSJung-uk Kim while (count > 0) { 6961f13597dSJung-uk Kim eax = padlock_xstore(&buf, 3); 6976f9291ceSJung-uk Kim if (!(eax & (1 << 6))) 6986f9291ceSJung-uk Kim return 0; /* RNG disabled */ 6991f13597dSJung-uk Kim /* this ---vv--- covers DC bias, Raw Bits and String Filter */ 7006f9291ceSJung-uk Kim if (eax & (0x1F << 10)) 7016f9291ceSJung-uk Kim return 0; 7026f9291ceSJung-uk Kim if ((eax & 0x1F) == 0) 7036f9291ceSJung-uk Kim continue; /* no data, retry... */ 7046f9291ceSJung-uk Kim if ((eax & 0x1F) != 1) 7056f9291ceSJung-uk Kim return 0; /* fatal failure... */ 7061f13597dSJung-uk Kim *output++ = (unsigned char)buf; 7071f13597dSJung-uk Kim count--; 7081f13597dSJung-uk Kim } 709e71b7053SJung-uk Kim OPENSSL_cleanse(&buf, sizeof(buf)); 7101f13597dSJung-uk Kim 7111f13597dSJung-uk Kim return 1; 7121f13597dSJung-uk Kim } 7131f13597dSJung-uk Kim 7141f13597dSJung-uk Kim /* Dummy but necessary function */ 7156f9291ceSJung-uk Kim static int padlock_rand_status(void) 7161f13597dSJung-uk Kim { 7171f13597dSJung-uk Kim return 1; 7181f13597dSJung-uk Kim } 7191f13597dSJung-uk Kim 7201f13597dSJung-uk Kim /* Prepare structure for registration */ 7211f13597dSJung-uk Kim static RAND_METHOD padlock_rand = { 7221f13597dSJung-uk Kim NULL, /* seed */ 7231f13597dSJung-uk Kim padlock_rand_bytes, /* bytes */ 7241f13597dSJung-uk Kim NULL, /* cleanup */ 7251f13597dSJung-uk Kim NULL, /* add */ 7261f13597dSJung-uk Kim padlock_rand_bytes, /* pseudorand */ 7271f13597dSJung-uk Kim padlock_rand_status, /* rand status */ 7281f13597dSJung-uk Kim }; 7291f13597dSJung-uk Kim 730e71b7053SJung-uk Kim # endif /* COMPILE_HW_PADLOCK */ 731e71b7053SJung-uk Kim # endif /* !OPENSSL_NO_HW_PADLOCK */ 732e71b7053SJung-uk Kim #endif /* !OPENSSL_NO_HW */ 733e71b7053SJung-uk Kim 734e71b7053SJung-uk Kim #if defined(OPENSSL_NO_HW) || defined(OPENSSL_NO_HW_PADLOCK) \ 735e71b7053SJung-uk Kim || !defined(COMPILE_HW_PADLOCK) 7361f13597dSJung-uk Kim # ifndef OPENSSL_NO_DYNAMIC_ENGINE 7371f13597dSJung-uk Kim OPENSSL_EXPORT 7381f13597dSJung-uk Kim int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); 7391f13597dSJung-uk Kim OPENSSL_EXPORT 7406f9291ceSJung-uk Kim int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) 7416f9291ceSJung-uk Kim { 7426f9291ceSJung-uk Kim return 0; 7436f9291ceSJung-uk Kim } 7446f9291ceSJung-uk Kim 7451f13597dSJung-uk Kim IMPLEMENT_DYNAMIC_CHECK_FN() 7461f13597dSJung-uk Kim # endif 747e71b7053SJung-uk Kim #endif 748