1e71b7053SJung-uk Kim /* 28f1ef87aSJung-uk Kim * Copyright 2004-2023 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 44610a21fdSJung-uk Kim # if 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 1478f1ef87aSJung-uk Kim # ifndef AES_ASM 1488f1ef87aSJung-uk Kim static int padlock_aes_set_encrypt_key(const unsigned char *userKey, 1498f1ef87aSJung-uk Kim const int bits, 1508f1ef87aSJung-uk Kim AES_KEY *key); 1518f1ef87aSJung-uk Kim static int padlock_aes_set_decrypt_key(const unsigned char *userKey, 1528f1ef87aSJung-uk Kim const int bits, 1538f1ef87aSJung-uk Kim AES_KEY *key); 1548f1ef87aSJung-uk Kim # define AES_ASM 1558f1ef87aSJung-uk Kim # define AES_set_encrypt_key padlock_aes_set_encrypt_key 1568f1ef87aSJung-uk Kim # define AES_set_decrypt_key padlock_aes_set_decrypt_key 1578f1ef87aSJung-uk Kim # include "../crypto/aes/aes_core.c" 1588f1ef87aSJung-uk Kim # endif 1598f1ef87aSJung-uk Kim 1606f9291ceSJung-uk Kim /* 1616f9291ceSJung-uk Kim * This stuff is needed if this ENGINE is being compiled into a 1626f9291ceSJung-uk Kim * self-contained shared-library. 1631f13597dSJung-uk Kim */ 164610a21fdSJung-uk Kim # ifndef OPENSSL_NO_DYNAMIC_ENGINE 1656f9291ceSJung-uk Kim static int padlock_bind_fn(ENGINE *e, const char *id) 1661f13597dSJung-uk Kim { 1671f13597dSJung-uk Kim if (id && (strcmp(id, padlock_id) != 0)) { 1681f13597dSJung-uk Kim return 0; 1691f13597dSJung-uk Kim } 1701f13597dSJung-uk Kim 1711f13597dSJung-uk Kim if (!padlock_bind_helper(e)) { 1721f13597dSJung-uk Kim return 0; 1731f13597dSJung-uk Kim } 1741f13597dSJung-uk Kim 1751f13597dSJung-uk Kim return 1; 1761f13597dSJung-uk Kim } 1771f13597dSJung-uk Kim 1781f13597dSJung-uk Kim IMPLEMENT_DYNAMIC_CHECK_FN() 1791f13597dSJung-uk Kim IMPLEMENT_DYNAMIC_BIND_FN(padlock_bind_fn) 180610a21fdSJung-uk Kim # endif /* !OPENSSL_NO_DYNAMIC_ENGINE */ 1811f13597dSJung-uk Kim /* ===== Here comes the "real" engine ===== */ 182e71b7053SJung-uk Kim 1831f13597dSJung-uk Kim /* Some AES-related constants */ 1841f13597dSJung-uk Kim # define AES_BLOCK_SIZE 16 1851f13597dSJung-uk Kim # define AES_KEY_SIZE_128 16 1861f13597dSJung-uk Kim # define AES_KEY_SIZE_192 24 1871f13597dSJung-uk Kim # define AES_KEY_SIZE_256 32 1886f9291ceSJung-uk Kim /* 1896f9291ceSJung-uk Kim * Here we store the status information relevant to the current context. 1901f13597dSJung-uk Kim */ 1916f9291ceSJung-uk Kim /* 1926f9291ceSJung-uk Kim * BIG FAT WARNING: Inline assembler in PADLOCK_XCRYPT_ASM() depends on 1936f9291ceSJung-uk Kim * the order of items in this structure. Don't blindly modify, reorder, 1946f9291ceSJung-uk Kim * etc! 1956f9291ceSJung-uk Kim */ 1966f9291ceSJung-uk Kim struct padlock_cipher_data { 1971f13597dSJung-uk Kim unsigned char iv[AES_BLOCK_SIZE]; /* Initialization vector */ 1986f9291ceSJung-uk Kim union { 1996f9291ceSJung-uk Kim unsigned int pad[4]; 2001f13597dSJung-uk Kim struct { 2011f13597dSJung-uk Kim int rounds:4; 2021f13597dSJung-uk Kim int dgst:1; /* n/a in C3 */ 2031f13597dSJung-uk Kim int align:1; /* n/a in C3 */ 2041f13597dSJung-uk Kim int ciphr:1; /* n/a in C3 */ 2051f13597dSJung-uk Kim unsigned int keygen:1; 2061f13597dSJung-uk Kim int interm:1; 2071f13597dSJung-uk Kim unsigned int encdec:1; 2081f13597dSJung-uk Kim int ksize:2; 2091f13597dSJung-uk Kim } b; 2101f13597dSJung-uk Kim } cword; /* Control word */ 2111f13597dSJung-uk Kim AES_KEY ks; /* Encryption key */ 2121f13597dSJung-uk Kim }; 2131f13597dSJung-uk Kim 214e71b7053SJung-uk Kim /* Interface to assembler module */ 215e71b7053SJung-uk Kim unsigned int padlock_capability(void); 216e71b7053SJung-uk Kim void padlock_key_bswap(AES_KEY *key); 217e71b7053SJung-uk Kim void padlock_verify_context(struct padlock_cipher_data *ctx); 218e71b7053SJung-uk Kim void padlock_reload_key(void); 219e71b7053SJung-uk Kim void padlock_aes_block(void *out, const void *inp, 220e71b7053SJung-uk Kim struct padlock_cipher_data *ctx); 221e71b7053SJung-uk Kim int padlock_ecb_encrypt(void *out, const void *inp, 222e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, size_t len); 223e71b7053SJung-uk Kim int padlock_cbc_encrypt(void *out, const void *inp, 224e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, size_t len); 225e71b7053SJung-uk Kim int padlock_cfb_encrypt(void *out, const void *inp, 226e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, size_t len); 227e71b7053SJung-uk Kim int padlock_ofb_encrypt(void *out, const void *inp, 228e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, size_t len); 229e71b7053SJung-uk Kim int padlock_ctr32_encrypt(void *out, const void *inp, 230e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, size_t len); 231e71b7053SJung-uk Kim int padlock_xstore(void *out, int edx); 232e71b7053SJung-uk Kim void padlock_sha1_oneshot(void *ctx, const void *inp, size_t len); 233e71b7053SJung-uk Kim void padlock_sha1(void *ctx, const void *inp, size_t len); 234e71b7053SJung-uk Kim void padlock_sha256_oneshot(void *ctx, const void *inp, size_t len); 235e71b7053SJung-uk Kim void padlock_sha256(void *ctx, const void *inp, size_t len); 2361f13597dSJung-uk Kim 2376f9291ceSJung-uk Kim /* 2386f9291ceSJung-uk Kim * Load supported features of the CPU to see if the PadLock is available. 2396f9291ceSJung-uk Kim */ 2406f9291ceSJung-uk Kim static int padlock_available(void) 2411f13597dSJung-uk Kim { 242e71b7053SJung-uk Kim unsigned int edx = padlock_capability(); 2431f13597dSJung-uk Kim 2441f13597dSJung-uk Kim /* Fill up some flags */ 2451f13597dSJung-uk Kim padlock_use_ace = ((edx & (0x3 << 6)) == (0x3 << 6)); 2461f13597dSJung-uk Kim padlock_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2)); 2471f13597dSJung-uk Kim 2481f13597dSJung-uk Kim return padlock_use_ace + padlock_use_rng; 2491f13597dSJung-uk Kim } 2501f13597dSJung-uk Kim 2511f13597dSJung-uk Kim /* ===== AES encryption/decryption ===== */ 252e71b7053SJung-uk Kim 2531f13597dSJung-uk Kim # if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb) 2541f13597dSJung-uk Kim # define NID_aes_128_cfb NID_aes_128_cfb128 2551f13597dSJung-uk Kim # endif 256e71b7053SJung-uk Kim 2571f13597dSJung-uk Kim # if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb) 2581f13597dSJung-uk Kim # define NID_aes_128_ofb NID_aes_128_ofb128 2591f13597dSJung-uk Kim # endif 260e71b7053SJung-uk Kim 2611f13597dSJung-uk Kim # if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb) 2621f13597dSJung-uk Kim # define NID_aes_192_cfb NID_aes_192_cfb128 2631f13597dSJung-uk Kim # endif 264e71b7053SJung-uk Kim 2651f13597dSJung-uk Kim # if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb) 2661f13597dSJung-uk Kim # define NID_aes_192_ofb NID_aes_192_ofb128 2671f13597dSJung-uk Kim # endif 268e71b7053SJung-uk Kim 2691f13597dSJung-uk Kim # if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb) 2701f13597dSJung-uk Kim # define NID_aes_256_cfb NID_aes_256_cfb128 2711f13597dSJung-uk Kim # endif 272e71b7053SJung-uk Kim 2731f13597dSJung-uk Kim # if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb) 2741f13597dSJung-uk Kim # define NID_aes_256_ofb NID_aes_256_ofb128 2751f13597dSJung-uk Kim # endif 276e71b7053SJung-uk Kim 277e71b7053SJung-uk Kim /* List of supported ciphers. */ 278e71b7053SJung-uk Kim static const int padlock_cipher_nids[] = { 2791f13597dSJung-uk Kim NID_aes_128_ecb, 2801f13597dSJung-uk Kim NID_aes_128_cbc, 2811f13597dSJung-uk Kim NID_aes_128_cfb, 2821f13597dSJung-uk Kim NID_aes_128_ofb, 283e71b7053SJung-uk Kim NID_aes_128_ctr, 2841f13597dSJung-uk Kim 2851f13597dSJung-uk Kim NID_aes_192_ecb, 2861f13597dSJung-uk Kim NID_aes_192_cbc, 2871f13597dSJung-uk Kim NID_aes_192_cfb, 2881f13597dSJung-uk Kim NID_aes_192_ofb, 289e71b7053SJung-uk Kim NID_aes_192_ctr, 2901f13597dSJung-uk Kim 2911f13597dSJung-uk Kim NID_aes_256_ecb, 2921f13597dSJung-uk Kim NID_aes_256_cbc, 2931f13597dSJung-uk Kim NID_aes_256_cfb, 2941f13597dSJung-uk Kim NID_aes_256_ofb, 295e71b7053SJung-uk Kim NID_aes_256_ctr 2961f13597dSJung-uk Kim }; 2976f9291ceSJung-uk Kim 2981f13597dSJung-uk Kim static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids) / 2991f13597dSJung-uk Kim sizeof(padlock_cipher_nids[0])); 3001f13597dSJung-uk Kim 3011f13597dSJung-uk Kim /* Function prototypes ... */ 3021f13597dSJung-uk Kim static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 3031f13597dSJung-uk Kim const unsigned char *iv, int enc); 3041f13597dSJung-uk Kim 3051f13597dSJung-uk Kim # define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \ 3061f13597dSJung-uk Kim ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F ) ) 3071f13597dSJung-uk Kim # define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\ 308e71b7053SJung-uk Kim NEAREST_ALIGNED(EVP_CIPHER_CTX_get_cipher_data(ctx))) 309e71b7053SJung-uk Kim 310e71b7053SJung-uk Kim static int 311e71b7053SJung-uk Kim padlock_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, 312e71b7053SJung-uk Kim const unsigned char *in_arg, size_t nbytes) 313e71b7053SJung-uk Kim { 314e71b7053SJung-uk Kim return padlock_ecb_encrypt(out_arg, in_arg, 315e71b7053SJung-uk Kim ALIGNED_CIPHER_DATA(ctx), nbytes); 316e71b7053SJung-uk Kim } 317e71b7053SJung-uk Kim 318e71b7053SJung-uk Kim static int 319e71b7053SJung-uk Kim padlock_cbc_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 int ret; 324e71b7053SJung-uk Kim 325e71b7053SJung-uk Kim memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); 326e71b7053SJung-uk Kim if ((ret = padlock_cbc_encrypt(out_arg, in_arg, cdata, nbytes))) 327e71b7053SJung-uk Kim memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); 328e71b7053SJung-uk Kim return ret; 329e71b7053SJung-uk Kim } 330e71b7053SJung-uk Kim 331e71b7053SJung-uk Kim static int 332e71b7053SJung-uk Kim padlock_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, 333e71b7053SJung-uk Kim const unsigned char *in_arg, size_t nbytes) 334e71b7053SJung-uk Kim { 335e71b7053SJung-uk Kim struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); 336e71b7053SJung-uk Kim size_t chunk; 337e71b7053SJung-uk Kim 338e71b7053SJung-uk Kim if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */ 339e71b7053SJung-uk Kim unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx); 340e71b7053SJung-uk Kim 341e71b7053SJung-uk Kim if (chunk >= AES_BLOCK_SIZE) 342e71b7053SJung-uk Kim return 0; /* bogus value */ 343e71b7053SJung-uk Kim 344e71b7053SJung-uk Kim if (EVP_CIPHER_CTX_encrypting(ctx)) 345e71b7053SJung-uk Kim while (chunk < AES_BLOCK_SIZE && nbytes != 0) { 346e71b7053SJung-uk Kim ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk]; 347e71b7053SJung-uk Kim chunk++, nbytes--; 348e71b7053SJung-uk Kim } else 349e71b7053SJung-uk Kim while (chunk < AES_BLOCK_SIZE && nbytes != 0) { 350e71b7053SJung-uk Kim unsigned char c = *(in_arg++); 351e71b7053SJung-uk Kim *(out_arg++) = c ^ ivp[chunk]; 352e71b7053SJung-uk Kim ivp[chunk++] = c, nbytes--; 353e71b7053SJung-uk Kim } 354e71b7053SJung-uk Kim 355e71b7053SJung-uk Kim EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE); 356e71b7053SJung-uk Kim } 357e71b7053SJung-uk Kim 358e71b7053SJung-uk Kim if (nbytes == 0) 359e71b7053SJung-uk Kim return 1; 360e71b7053SJung-uk Kim 361e71b7053SJung-uk Kim memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); 362e71b7053SJung-uk Kim 363e71b7053SJung-uk Kim if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) { 364e71b7053SJung-uk Kim if (!padlock_cfb_encrypt(out_arg, in_arg, cdata, chunk)) 365e71b7053SJung-uk Kim return 0; 366e71b7053SJung-uk Kim nbytes -= chunk; 367e71b7053SJung-uk Kim } 368e71b7053SJung-uk Kim 369e71b7053SJung-uk Kim if (nbytes) { 370e71b7053SJung-uk Kim unsigned char *ivp = cdata->iv; 371e71b7053SJung-uk Kim 372e71b7053SJung-uk Kim out_arg += chunk; 373e71b7053SJung-uk Kim in_arg += chunk; 374e71b7053SJung-uk Kim EVP_CIPHER_CTX_set_num(ctx, nbytes); 375e71b7053SJung-uk Kim if (cdata->cword.b.encdec) { 376e71b7053SJung-uk Kim cdata->cword.b.encdec = 0; 377e71b7053SJung-uk Kim padlock_reload_key(); 378e71b7053SJung-uk Kim padlock_aes_block(ivp, ivp, cdata); 379e71b7053SJung-uk Kim cdata->cword.b.encdec = 1; 380e71b7053SJung-uk Kim padlock_reload_key(); 381e71b7053SJung-uk Kim while (nbytes) { 382e71b7053SJung-uk Kim unsigned char c = *(in_arg++); 383e71b7053SJung-uk Kim *(out_arg++) = c ^ *ivp; 384e71b7053SJung-uk Kim *(ivp++) = c, nbytes--; 385e71b7053SJung-uk Kim } 386e71b7053SJung-uk Kim } else { 387e71b7053SJung-uk Kim padlock_reload_key(); 388e71b7053SJung-uk Kim padlock_aes_block(ivp, ivp, cdata); 389e71b7053SJung-uk Kim padlock_reload_key(); 390e71b7053SJung-uk Kim while (nbytes) { 391e71b7053SJung-uk Kim *ivp = *(out_arg++) = *(in_arg++) ^ *ivp; 392e71b7053SJung-uk Kim ivp++, nbytes--; 393e71b7053SJung-uk Kim } 394e71b7053SJung-uk Kim } 395e71b7053SJung-uk Kim } 396e71b7053SJung-uk Kim 397e71b7053SJung-uk Kim memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); 398e71b7053SJung-uk Kim 399e71b7053SJung-uk Kim return 1; 400e71b7053SJung-uk Kim } 401e71b7053SJung-uk Kim 402e71b7053SJung-uk Kim static int 403e71b7053SJung-uk Kim padlock_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, 404e71b7053SJung-uk Kim const unsigned char *in_arg, size_t nbytes) 405e71b7053SJung-uk Kim { 406e71b7053SJung-uk Kim struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); 407e71b7053SJung-uk Kim size_t chunk; 408e71b7053SJung-uk Kim 409e71b7053SJung-uk Kim /* 410e71b7053SJung-uk Kim * ctx->num is maintained in byte-oriented modes, such as CFB and OFB... 411e71b7053SJung-uk Kim */ 412e71b7053SJung-uk Kim if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */ 413e71b7053SJung-uk Kim unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx); 414e71b7053SJung-uk Kim 415e71b7053SJung-uk Kim if (chunk >= AES_BLOCK_SIZE) 416e71b7053SJung-uk Kim return 0; /* bogus value */ 417e71b7053SJung-uk Kim 418e71b7053SJung-uk Kim while (chunk < AES_BLOCK_SIZE && nbytes != 0) { 419e71b7053SJung-uk Kim *(out_arg++) = *(in_arg++) ^ ivp[chunk]; 420e71b7053SJung-uk Kim chunk++, nbytes--; 421e71b7053SJung-uk Kim } 422e71b7053SJung-uk Kim 423e71b7053SJung-uk Kim EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE); 424e71b7053SJung-uk Kim } 425e71b7053SJung-uk Kim 426e71b7053SJung-uk Kim if (nbytes == 0) 427e71b7053SJung-uk Kim return 1; 428e71b7053SJung-uk Kim 429e71b7053SJung-uk Kim memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); 430e71b7053SJung-uk Kim 431e71b7053SJung-uk Kim if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) { 432e71b7053SJung-uk Kim if (!padlock_ofb_encrypt(out_arg, in_arg, cdata, chunk)) 433e71b7053SJung-uk Kim return 0; 434e71b7053SJung-uk Kim nbytes -= chunk; 435e71b7053SJung-uk Kim } 436e71b7053SJung-uk Kim 437e71b7053SJung-uk Kim if (nbytes) { 438e71b7053SJung-uk Kim unsigned char *ivp = cdata->iv; 439e71b7053SJung-uk Kim 440e71b7053SJung-uk Kim out_arg += chunk; 441e71b7053SJung-uk Kim in_arg += chunk; 442e71b7053SJung-uk Kim EVP_CIPHER_CTX_set_num(ctx, nbytes); 443e71b7053SJung-uk Kim padlock_reload_key(); /* empirically found */ 444e71b7053SJung-uk Kim padlock_aes_block(ivp, ivp, cdata); 445e71b7053SJung-uk Kim padlock_reload_key(); /* empirically found */ 446e71b7053SJung-uk Kim while (nbytes) { 447e71b7053SJung-uk Kim *(out_arg++) = *(in_arg++) ^ *ivp; 448e71b7053SJung-uk Kim ivp++, nbytes--; 449e71b7053SJung-uk Kim } 450e71b7053SJung-uk Kim } 451e71b7053SJung-uk Kim 452e71b7053SJung-uk Kim memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); 453e71b7053SJung-uk Kim 454e71b7053SJung-uk Kim return 1; 455e71b7053SJung-uk Kim } 456e71b7053SJung-uk Kim 457e71b7053SJung-uk Kim static void padlock_ctr32_encrypt_glue(const unsigned char *in, 458e71b7053SJung-uk Kim unsigned char *out, size_t blocks, 459e71b7053SJung-uk Kim struct padlock_cipher_data *ctx, 460e71b7053SJung-uk Kim const unsigned char *ivec) 461e71b7053SJung-uk Kim { 462e71b7053SJung-uk Kim memcpy(ctx->iv, ivec, AES_BLOCK_SIZE); 463e71b7053SJung-uk Kim padlock_ctr32_encrypt(out, in, ctx, AES_BLOCK_SIZE * blocks); 464e71b7053SJung-uk Kim } 465e71b7053SJung-uk Kim 466e71b7053SJung-uk Kim static int 467e71b7053SJung-uk Kim padlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, 468e71b7053SJung-uk Kim const unsigned char *in_arg, size_t nbytes) 469e71b7053SJung-uk Kim { 470e71b7053SJung-uk Kim struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); 471e71b7053SJung-uk Kim unsigned int num = EVP_CIPHER_CTX_num(ctx); 472e71b7053SJung-uk Kim 473e71b7053SJung-uk Kim CRYPTO_ctr128_encrypt_ctr32(in_arg, out_arg, nbytes, 474e71b7053SJung-uk Kim cdata, EVP_CIPHER_CTX_iv_noconst(ctx), 475e71b7053SJung-uk Kim EVP_CIPHER_CTX_buf_noconst(ctx), &num, 476e71b7053SJung-uk Kim (ctr128_f) padlock_ctr32_encrypt_glue); 477e71b7053SJung-uk Kim 478e71b7053SJung-uk Kim EVP_CIPHER_CTX_set_num(ctx, (size_t)num); 479e71b7053SJung-uk Kim return 1; 480e71b7053SJung-uk Kim } 4811f13597dSJung-uk Kim 4821f13597dSJung-uk Kim # define EVP_CIPHER_block_size_ECB AES_BLOCK_SIZE 4831f13597dSJung-uk Kim # define EVP_CIPHER_block_size_CBC AES_BLOCK_SIZE 4841f13597dSJung-uk Kim # define EVP_CIPHER_block_size_OFB 1 4851f13597dSJung-uk Kim # define EVP_CIPHER_block_size_CFB 1 486e71b7053SJung-uk Kim # define EVP_CIPHER_block_size_CTR 1 4871f13597dSJung-uk Kim 4886f9291ceSJung-uk Kim /* 4896f9291ceSJung-uk Kim * Declaring so many ciphers by hand would be a pain. Instead introduce a bit 4906f9291ceSJung-uk Kim * of preprocessor magic :-) 4916f9291ceSJung-uk Kim */ 4921f13597dSJung-uk Kim # define DECLARE_AES_EVP(ksize,lmode,umode) \ 493e71b7053SJung-uk Kim static EVP_CIPHER *_hidden_aes_##ksize##_##lmode = NULL; \ 494e71b7053SJung-uk Kim static const EVP_CIPHER *padlock_aes_##ksize##_##lmode(void) \ 495e71b7053SJung-uk Kim { \ 496e71b7053SJung-uk Kim if (_hidden_aes_##ksize##_##lmode == NULL \ 497e71b7053SJung-uk Kim && ((_hidden_aes_##ksize##_##lmode = \ 498e71b7053SJung-uk Kim EVP_CIPHER_meth_new(NID_aes_##ksize##_##lmode, \ 4991f13597dSJung-uk Kim EVP_CIPHER_block_size_##umode, \ 500e71b7053SJung-uk Kim AES_KEY_SIZE_##ksize)) == NULL \ 501e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_##ksize##_##lmode, \ 502e71b7053SJung-uk Kim AES_BLOCK_SIZE) \ 503e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_flags(_hidden_aes_##ksize##_##lmode, \ 504e71b7053SJung-uk Kim 0 | EVP_CIPH_##umode##_MODE) \ 505e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_init(_hidden_aes_##ksize##_##lmode, \ 506e71b7053SJung-uk Kim padlock_aes_init_key) \ 507e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_##ksize##_##lmode, \ 508e71b7053SJung-uk Kim padlock_##lmode##_cipher) \ 509e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_##ksize##_##lmode, \ 510e71b7053SJung-uk Kim sizeof(struct padlock_cipher_data) + 16) \ 511e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_##ksize##_##lmode, \ 512e71b7053SJung-uk Kim EVP_CIPHER_set_asn1_iv) \ 513e71b7053SJung-uk Kim || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_##ksize##_##lmode, \ 514e71b7053SJung-uk Kim EVP_CIPHER_get_asn1_iv))) { \ 515e71b7053SJung-uk Kim EVP_CIPHER_meth_free(_hidden_aes_##ksize##_##lmode); \ 516e71b7053SJung-uk Kim _hidden_aes_##ksize##_##lmode = NULL; \ 517e71b7053SJung-uk Kim } \ 518e71b7053SJung-uk Kim return _hidden_aes_##ksize##_##lmode; \ 5191f13597dSJung-uk Kim } 5201f13597dSJung-uk Kim 521e71b7053SJung-uk Kim DECLARE_AES_EVP(128, ecb, ECB) 522e71b7053SJung-uk Kim DECLARE_AES_EVP(128, cbc, CBC) 523e71b7053SJung-uk Kim DECLARE_AES_EVP(128, cfb, CFB) 524e71b7053SJung-uk Kim DECLARE_AES_EVP(128, ofb, OFB) 525e71b7053SJung-uk Kim DECLARE_AES_EVP(128, ctr, CTR) 5261f13597dSJung-uk Kim 527e71b7053SJung-uk Kim DECLARE_AES_EVP(192, ecb, ECB) 528e71b7053SJung-uk Kim DECLARE_AES_EVP(192, cbc, CBC) 529e71b7053SJung-uk Kim DECLARE_AES_EVP(192, cfb, CFB) 530e71b7053SJung-uk Kim DECLARE_AES_EVP(192, ofb, OFB) 531e71b7053SJung-uk Kim DECLARE_AES_EVP(192, ctr, CTR) 5321f13597dSJung-uk Kim 533e71b7053SJung-uk Kim DECLARE_AES_EVP(256, ecb, ECB) 534e71b7053SJung-uk Kim DECLARE_AES_EVP(256, cbc, CBC) 535e71b7053SJung-uk Kim DECLARE_AES_EVP(256, cfb, CFB) 536e71b7053SJung-uk Kim DECLARE_AES_EVP(256, ofb, OFB) 537e71b7053SJung-uk Kim DECLARE_AES_EVP(256, ctr, CTR) 5381f13597dSJung-uk Kim 5391f13597dSJung-uk Kim static int 5406f9291ceSJung-uk Kim padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, 5416f9291ceSJung-uk Kim int nid) 5421f13597dSJung-uk Kim { 5431f13597dSJung-uk Kim /* No specific cipher => return a list of supported nids ... */ 5441f13597dSJung-uk Kim if (!cipher) { 5451f13597dSJung-uk Kim *nids = padlock_cipher_nids; 5461f13597dSJung-uk Kim return padlock_cipher_nids_num; 5471f13597dSJung-uk Kim } 5481f13597dSJung-uk Kim 5491f13597dSJung-uk Kim /* ... or the requested "cipher" otherwise */ 5501f13597dSJung-uk Kim switch (nid) { 5511f13597dSJung-uk Kim case NID_aes_128_ecb: 552e71b7053SJung-uk Kim *cipher = padlock_aes_128_ecb(); 5531f13597dSJung-uk Kim break; 5541f13597dSJung-uk Kim case NID_aes_128_cbc: 555e71b7053SJung-uk Kim *cipher = padlock_aes_128_cbc(); 5561f13597dSJung-uk Kim break; 5571f13597dSJung-uk Kim case NID_aes_128_cfb: 558e71b7053SJung-uk Kim *cipher = padlock_aes_128_cfb(); 5591f13597dSJung-uk Kim break; 5601f13597dSJung-uk Kim case NID_aes_128_ofb: 561e71b7053SJung-uk Kim *cipher = padlock_aes_128_ofb(); 562e71b7053SJung-uk Kim break; 563e71b7053SJung-uk Kim case NID_aes_128_ctr: 564e71b7053SJung-uk Kim *cipher = padlock_aes_128_ctr(); 5651f13597dSJung-uk Kim break; 5661f13597dSJung-uk Kim 5671f13597dSJung-uk Kim case NID_aes_192_ecb: 568e71b7053SJung-uk Kim *cipher = padlock_aes_192_ecb(); 5691f13597dSJung-uk Kim break; 5701f13597dSJung-uk Kim case NID_aes_192_cbc: 571e71b7053SJung-uk Kim *cipher = padlock_aes_192_cbc(); 5721f13597dSJung-uk Kim break; 5731f13597dSJung-uk Kim case NID_aes_192_cfb: 574e71b7053SJung-uk Kim *cipher = padlock_aes_192_cfb(); 5751f13597dSJung-uk Kim break; 5761f13597dSJung-uk Kim case NID_aes_192_ofb: 577e71b7053SJung-uk Kim *cipher = padlock_aes_192_ofb(); 578e71b7053SJung-uk Kim break; 579e71b7053SJung-uk Kim case NID_aes_192_ctr: 580e71b7053SJung-uk Kim *cipher = padlock_aes_192_ctr(); 5811f13597dSJung-uk Kim break; 5821f13597dSJung-uk Kim 5831f13597dSJung-uk Kim case NID_aes_256_ecb: 584e71b7053SJung-uk Kim *cipher = padlock_aes_256_ecb(); 5851f13597dSJung-uk Kim break; 5861f13597dSJung-uk Kim case NID_aes_256_cbc: 587e71b7053SJung-uk Kim *cipher = padlock_aes_256_cbc(); 5881f13597dSJung-uk Kim break; 5891f13597dSJung-uk Kim case NID_aes_256_cfb: 590e71b7053SJung-uk Kim *cipher = padlock_aes_256_cfb(); 5911f13597dSJung-uk Kim break; 5921f13597dSJung-uk Kim case NID_aes_256_ofb: 593e71b7053SJung-uk Kim *cipher = padlock_aes_256_ofb(); 594e71b7053SJung-uk Kim break; 595e71b7053SJung-uk Kim case NID_aes_256_ctr: 596e71b7053SJung-uk Kim *cipher = padlock_aes_256_ctr(); 5971f13597dSJung-uk Kim break; 5981f13597dSJung-uk Kim 5991f13597dSJung-uk Kim default: 6001f13597dSJung-uk Kim /* Sorry, we don't support this NID */ 6011f13597dSJung-uk Kim *cipher = NULL; 6021f13597dSJung-uk Kim return 0; 6031f13597dSJung-uk Kim } 6041f13597dSJung-uk Kim 6051f13597dSJung-uk Kim return 1; 6061f13597dSJung-uk Kim } 6071f13597dSJung-uk Kim 6081f13597dSJung-uk Kim /* Prepare the encryption key for PadLock usage */ 6091f13597dSJung-uk Kim static int 6101f13597dSJung-uk Kim padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 6111f13597dSJung-uk Kim const unsigned char *iv, int enc) 6121f13597dSJung-uk Kim { 6131f13597dSJung-uk Kim struct padlock_cipher_data *cdata; 6141f13597dSJung-uk Kim int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8; 615e71b7053SJung-uk Kim unsigned long mode = EVP_CIPHER_CTX_mode(ctx); 6161f13597dSJung-uk Kim 6176f9291ceSJung-uk Kim if (key == NULL) 6186f9291ceSJung-uk Kim return 0; /* ERROR */ 6191f13597dSJung-uk Kim 6201f13597dSJung-uk Kim cdata = ALIGNED_CIPHER_DATA(ctx); 621e71b7053SJung-uk Kim memset(cdata, 0, sizeof(*cdata)); 6221f13597dSJung-uk Kim 6231f13597dSJung-uk Kim /* Prepare Control word. */ 624e71b7053SJung-uk Kim if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE) 6251f13597dSJung-uk Kim cdata->cword.b.encdec = 0; 6261f13597dSJung-uk Kim else 627e71b7053SJung-uk Kim cdata->cword.b.encdec = (EVP_CIPHER_CTX_encrypting(ctx) == 0); 6281f13597dSJung-uk Kim cdata->cword.b.rounds = 10 + (key_len - 128) / 32; 6291f13597dSJung-uk Kim cdata->cword.b.ksize = (key_len - 128) / 64; 6301f13597dSJung-uk Kim 6311f13597dSJung-uk Kim switch (key_len) { 6321f13597dSJung-uk Kim case 128: 6336f9291ceSJung-uk Kim /* 6346f9291ceSJung-uk Kim * PadLock can generate an extended key for AES128 in hardware 6356f9291ceSJung-uk Kim */ 6361f13597dSJung-uk Kim memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128); 6371f13597dSJung-uk Kim cdata->cword.b.keygen = 0; 6381f13597dSJung-uk Kim break; 6391f13597dSJung-uk Kim 6401f13597dSJung-uk Kim case 192: 6411f13597dSJung-uk Kim case 256: 6426f9291ceSJung-uk Kim /* 6436f9291ceSJung-uk Kim * Generate an extended AES key in software. Needed for AES192/AES256 6446f9291ceSJung-uk Kim */ 6456f9291ceSJung-uk Kim /* 6466f9291ceSJung-uk Kim * Well, the above applies to Stepping 8 CPUs and is listed as 6476f9291ceSJung-uk Kim * hardware errata. They most likely will fix it at some point and 6486f9291ceSJung-uk Kim * then a check for stepping would be due here. 6496f9291ceSJung-uk Kim */ 650e71b7053SJung-uk Kim if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) 651e71b7053SJung-uk Kim && !enc) 6521f13597dSJung-uk Kim AES_set_decrypt_key(key, key_len, &cdata->ks); 653e71b7053SJung-uk Kim else 654e71b7053SJung-uk Kim AES_set_encrypt_key(key, key_len, &cdata->ks); 6556f9291ceSJung-uk Kim /* 6566f9291ceSJung-uk Kim * OpenSSL C functions use byte-swapped extended key. 6576f9291ceSJung-uk Kim */ 658e71b7053SJung-uk Kim padlock_key_bswap(&cdata->ks); 6591f13597dSJung-uk Kim cdata->cword.b.keygen = 1; 6601f13597dSJung-uk Kim break; 6611f13597dSJung-uk Kim 6621f13597dSJung-uk Kim default: 6631f13597dSJung-uk Kim /* ERROR */ 6641f13597dSJung-uk Kim return 0; 6651f13597dSJung-uk Kim } 6661f13597dSJung-uk Kim 6671f13597dSJung-uk Kim /* 6681f13597dSJung-uk Kim * This is done to cover for cases when user reuses the 6691f13597dSJung-uk Kim * context for new key. The catch is that if we don't do 6701f13597dSJung-uk Kim * this, padlock_eas_cipher might proceed with old key... 6711f13597dSJung-uk Kim */ 6721f13597dSJung-uk Kim padlock_reload_key(); 6731f13597dSJung-uk Kim 6741f13597dSJung-uk Kim return 1; 6751f13597dSJung-uk Kim } 6761f13597dSJung-uk Kim 6771f13597dSJung-uk Kim /* ===== Random Number Generator ===== */ 6781f13597dSJung-uk Kim /* 6791f13597dSJung-uk Kim * This code is not engaged. The reason is that it does not comply 6801f13597dSJung-uk Kim * with recommendations for VIA RNG usage for secure applications 6811f13597dSJung-uk Kim * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it 6821f13597dSJung-uk Kim * provide meaningful error control... 6831f13597dSJung-uk Kim */ 6846f9291ceSJung-uk Kim /* 6856f9291ceSJung-uk Kim * Wrapper that provides an interface between the API and the raw PadLock 6866f9291ceSJung-uk Kim * RNG 6876f9291ceSJung-uk Kim */ 6886f9291ceSJung-uk Kim static int padlock_rand_bytes(unsigned char *output, int count) 6891f13597dSJung-uk Kim { 6901f13597dSJung-uk Kim unsigned int eax, buf; 6911f13597dSJung-uk Kim 6921f13597dSJung-uk Kim while (count >= 8) { 6931f13597dSJung-uk Kim eax = padlock_xstore(output, 0); 6946f9291ceSJung-uk Kim if (!(eax & (1 << 6))) 6956f9291ceSJung-uk Kim return 0; /* RNG disabled */ 6961f13597dSJung-uk Kim /* this ---vv--- covers DC bias, Raw Bits and String Filter */ 6976f9291ceSJung-uk Kim if (eax & (0x1F << 10)) 6986f9291ceSJung-uk Kim return 0; 6996f9291ceSJung-uk Kim if ((eax & 0x1F) == 0) 7006f9291ceSJung-uk Kim continue; /* no data, retry... */ 7016f9291ceSJung-uk Kim if ((eax & 0x1F) != 8) 7026f9291ceSJung-uk Kim return 0; /* fatal failure... */ 7031f13597dSJung-uk Kim output += 8; 7041f13597dSJung-uk Kim count -= 8; 7051f13597dSJung-uk Kim } 7061f13597dSJung-uk Kim while (count > 0) { 7071f13597dSJung-uk Kim eax = padlock_xstore(&buf, 3); 7086f9291ceSJung-uk Kim if (!(eax & (1 << 6))) 7096f9291ceSJung-uk Kim return 0; /* RNG disabled */ 7101f13597dSJung-uk Kim /* this ---vv--- covers DC bias, Raw Bits and String Filter */ 7116f9291ceSJung-uk Kim if (eax & (0x1F << 10)) 7126f9291ceSJung-uk Kim return 0; 7136f9291ceSJung-uk Kim if ((eax & 0x1F) == 0) 7146f9291ceSJung-uk Kim continue; /* no data, retry... */ 7156f9291ceSJung-uk Kim if ((eax & 0x1F) != 1) 7166f9291ceSJung-uk Kim return 0; /* fatal failure... */ 7171f13597dSJung-uk Kim *output++ = (unsigned char)buf; 7181f13597dSJung-uk Kim count--; 7191f13597dSJung-uk Kim } 720e71b7053SJung-uk Kim OPENSSL_cleanse(&buf, sizeof(buf)); 7211f13597dSJung-uk Kim 7221f13597dSJung-uk Kim return 1; 7231f13597dSJung-uk Kim } 7241f13597dSJung-uk Kim 7251f13597dSJung-uk Kim /* Dummy but necessary function */ 7266f9291ceSJung-uk Kim static int padlock_rand_status(void) 7271f13597dSJung-uk Kim { 7281f13597dSJung-uk Kim return 1; 7291f13597dSJung-uk Kim } 7301f13597dSJung-uk Kim 7311f13597dSJung-uk Kim /* Prepare structure for registration */ 7321f13597dSJung-uk Kim static RAND_METHOD padlock_rand = { 7331f13597dSJung-uk Kim NULL, /* seed */ 7341f13597dSJung-uk Kim padlock_rand_bytes, /* bytes */ 7351f13597dSJung-uk Kim NULL, /* cleanup */ 7361f13597dSJung-uk Kim NULL, /* add */ 7371f13597dSJung-uk Kim padlock_rand_bytes, /* pseudorand */ 7381f13597dSJung-uk Kim padlock_rand_status, /* rand status */ 7391f13597dSJung-uk Kim }; 7401f13597dSJung-uk Kim 741e71b7053SJung-uk Kim # endif /* COMPILE_HW_PADLOCK */ 742e71b7053SJung-uk Kim # endif /* !OPENSSL_NO_HW_PADLOCK */ 743e71b7053SJung-uk Kim #endif /* !OPENSSL_NO_HW */ 744e71b7053SJung-uk Kim 745e71b7053SJung-uk Kim #if defined(OPENSSL_NO_HW) || defined(OPENSSL_NO_HW_PADLOCK) \ 746e71b7053SJung-uk Kim || !defined(COMPILE_HW_PADLOCK) 7471f13597dSJung-uk Kim # ifndef OPENSSL_NO_DYNAMIC_ENGINE 7481f13597dSJung-uk Kim OPENSSL_EXPORT 7491f13597dSJung-uk Kim int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); 7501f13597dSJung-uk Kim OPENSSL_EXPORT 7516f9291ceSJung-uk Kim int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) 7526f9291ceSJung-uk Kim { 7536f9291ceSJung-uk Kim return 0; 7546f9291ceSJung-uk Kim } 7556f9291ceSJung-uk Kim 7561f13597dSJung-uk Kim IMPLEMENT_DYNAMIC_CHECK_FN() 7571f13597dSJung-uk Kim # endif 758e71b7053SJung-uk Kim #endif 759