From aa4d426b4d3527d7e166df1a05058c9a4a0f6683 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Fri, 30 Apr 2021 00:33:56 +0200 Subject: initial/final commit --- openssl-1.1.0h/engines/e_padlock.c | 747 +++++++++++++++++++++++++++++++++++++ 1 file changed, 747 insertions(+) create mode 100644 openssl-1.1.0h/engines/e_padlock.c (limited to 'openssl-1.1.0h/engines/e_padlock.c') diff --git a/openssl-1.1.0h/engines/e_padlock.c b/openssl-1.1.0h/engines/e_padlock.c new file mode 100644 index 0000000..b86f165 --- /dev/null +++ b/openssl-1.1.0h/engines/e_padlock.c @@ -0,0 +1,747 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_HW +# ifndef OPENSSL_NO_HW_PADLOCK + +/* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */ +# if (OPENSSL_VERSION_NUMBER >= 0x00908000L) +# ifndef OPENSSL_NO_DYNAMIC_ENGINE +# define DYNAMIC_ENGINE +# endif +# elif (OPENSSL_VERSION_NUMBER >= 0x00907000L) +# ifdef ENGINE_DYNAMIC_SUPPORT +# define DYNAMIC_ENGINE +# endif +# else +# error "Only OpenSSL >= 0.9.7 is supported" +# endif + +/* + * VIA PadLock AES is available *ONLY* on some x86 CPUs. Not only that it + * doesn't exist elsewhere, but it even can't be compiled on other platforms! + */ + +# undef COMPILE_HW_PADLOCK +# if !defined(I386_ONLY) && defined(PADLOCK_ASM) +# define COMPILE_HW_PADLOCK +# ifdef OPENSSL_NO_DYNAMIC_ENGINE +static ENGINE *ENGINE_padlock(void); +# endif +# endif + +# ifdef OPENSSL_NO_DYNAMIC_ENGINE +void engine_load_padlock_int(void); +void engine_load_padlock_int(void) +{ +/* On non-x86 CPUs it just returns. */ +# ifdef COMPILE_HW_PADLOCK + ENGINE *toadd = ENGINE_padlock(); + if (!toadd) + return; + ENGINE_add(toadd); + ENGINE_free(toadd); + ERR_clear_error(); +# endif +} + +# endif + +# ifdef COMPILE_HW_PADLOCK + +/* Function for ENGINE detection and control */ +static int padlock_available(void); +static int padlock_init(ENGINE *e); + +/* RNG Stuff */ +static RAND_METHOD padlock_rand; + +/* Cipher Stuff */ +static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); + +/* Engine names */ +static const char *padlock_id = "padlock"; +static char padlock_name[100]; + +/* Available features */ +static int padlock_use_ace = 0; /* Advanced Cryptography Engine */ +static int padlock_use_rng = 0; /* Random Number Generator */ + +/* ===== Engine "management" functions ===== */ + +/* Prepare the ENGINE structure for registration */ +static int padlock_bind_helper(ENGINE *e) +{ + /* Check available features */ + padlock_available(); + + /* + * RNG is currently disabled for reasons discussed in commentary just + * before padlock_rand_bytes function. + */ + padlock_use_rng = 0; + + /* Generate a nice engine name with available features */ + BIO_snprintf(padlock_name, sizeof(padlock_name), + "VIA PadLock (%s, %s)", + padlock_use_rng ? "RNG" : "no-RNG", + padlock_use_ace ? "ACE" : "no-ACE"); + + /* Register everything or return with an error */ + if (!ENGINE_set_id(e, padlock_id) || + !ENGINE_set_name(e, padlock_name) || + !ENGINE_set_init_function(e, padlock_init) || + (padlock_use_ace && !ENGINE_set_ciphers(e, padlock_ciphers)) || + (padlock_use_rng && !ENGINE_set_RAND(e, &padlock_rand))) { + return 0; + } + + /* Everything looks good */ + return 1; +} + +# ifdef OPENSSL_NO_DYNAMIC_ENGINE +/* Constructor */ +static ENGINE *ENGINE_padlock(void) +{ + ENGINE *eng = ENGINE_new(); + + if (eng == NULL) { + return NULL; + } + + if (!padlock_bind_helper(eng)) { + ENGINE_free(eng); + return NULL; + } + + return eng; +} +# endif + +/* Check availability of the engine */ +static int padlock_init(ENGINE *e) +{ + return (padlock_use_rng || padlock_use_ace); +} + +/* + * This stuff is needed if this ENGINE is being compiled into a + * self-contained shared-library. + */ +# ifdef DYNAMIC_ENGINE +static int padlock_bind_fn(ENGINE *e, const char *id) +{ + if (id && (strcmp(id, padlock_id) != 0)) { + return 0; + } + + if (!padlock_bind_helper(e)) { + return 0; + } + + return 1; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(padlock_bind_fn) +# endif /* DYNAMIC_ENGINE */ +/* ===== Here comes the "real" engine ===== */ + +/* Some AES-related constants */ +# define AES_BLOCK_SIZE 16 +# define AES_KEY_SIZE_128 16 +# define AES_KEY_SIZE_192 24 +# define AES_KEY_SIZE_256 32 + /* + * Here we store the status information relevant to the current context. + */ + /* + * BIG FAT WARNING: Inline assembler in PADLOCK_XCRYPT_ASM() depends on + * the order of items in this structure. Don't blindly modify, reorder, + * etc! + */ +struct padlock_cipher_data { + unsigned char iv[AES_BLOCK_SIZE]; /* Initialization vector */ + union { + unsigned int pad[4]; + struct { + int rounds:4; + int dgst:1; /* n/a in C3 */ + int align:1; /* n/a in C3 */ + int ciphr:1; /* n/a in C3 */ + unsigned int keygen:1; + int interm:1; + unsigned int encdec:1; + int ksize:2; + } b; + } cword; /* Control word */ + AES_KEY ks; /* Encryption key */ +}; + +/* Interface to assembler module */ +unsigned int padlock_capability(); +void padlock_key_bswap(AES_KEY *key); +void padlock_verify_context(struct padlock_cipher_data *ctx); +void padlock_reload_key(); +void padlock_aes_block(void *out, const void *inp, + struct padlock_cipher_data *ctx); +int padlock_ecb_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +int padlock_cbc_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +int padlock_cfb_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +int padlock_ofb_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +int padlock_ctr32_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +int padlock_xstore(void *out, int edx); +void padlock_sha1_oneshot(void *ctx, const void *inp, size_t len); +void padlock_sha1(void *ctx, const void *inp, size_t len); +void padlock_sha256_oneshot(void *ctx, const void *inp, size_t len); +void padlock_sha256(void *ctx, const void *inp, size_t len); + +/* + * Load supported features of the CPU to see if the PadLock is available. + */ +static int padlock_available(void) +{ + unsigned int edx = padlock_capability(); + + /* Fill up some flags */ + padlock_use_ace = ((edx & (0x3 << 6)) == (0x3 << 6)); + padlock_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2)); + + return padlock_use_ace + padlock_use_rng; +} + +/* ===== AES encryption/decryption ===== */ + +# if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb) +# define NID_aes_128_cfb NID_aes_128_cfb128 +# endif + +# if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb) +# define NID_aes_128_ofb NID_aes_128_ofb128 +# endif + +# if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb) +# define NID_aes_192_cfb NID_aes_192_cfb128 +# endif + +# if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb) +# define NID_aes_192_ofb NID_aes_192_ofb128 +# endif + +# if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb) +# define NID_aes_256_cfb NID_aes_256_cfb128 +# endif + +# if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb) +# define NID_aes_256_ofb NID_aes_256_ofb128 +# endif + +/* List of supported ciphers. */ +static const int padlock_cipher_nids[] = { + NID_aes_128_ecb, + NID_aes_128_cbc, + NID_aes_128_cfb, + NID_aes_128_ofb, + NID_aes_128_ctr, + + NID_aes_192_ecb, + NID_aes_192_cbc, + NID_aes_192_cfb, + NID_aes_192_ofb, + NID_aes_192_ctr, + + NID_aes_256_ecb, + NID_aes_256_cbc, + NID_aes_256_cfb, + NID_aes_256_ofb, + NID_aes_256_ctr +}; + +static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids) / + sizeof(padlock_cipher_nids[0])); + +/* Function prototypes ... */ +static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +# define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \ + ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F ) ) +# define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\ + NEAREST_ALIGNED(EVP_CIPHER_CTX_get_cipher_data(ctx))) + +static int +padlock_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + return padlock_ecb_encrypt(out_arg, in_arg, + ALIGNED_CIPHER_DATA(ctx), nbytes); +} + +static int +padlock_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); + int ret; + + memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); + if ((ret = padlock_cbc_encrypt(out_arg, in_arg, cdata, nbytes))) + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); + return ret; +} + +static int +padlock_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); + size_t chunk; + + if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */ + unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx); + + if (chunk >= AES_BLOCK_SIZE) + return 0; /* bogus value */ + + if (EVP_CIPHER_CTX_encrypting(ctx)) + while (chunk < AES_BLOCK_SIZE && nbytes != 0) { + ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk]; + chunk++, nbytes--; + } else + while (chunk < AES_BLOCK_SIZE && nbytes != 0) { + unsigned char c = *(in_arg++); + *(out_arg++) = c ^ ivp[chunk]; + ivp[chunk++] = c, nbytes--; + } + + EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE); + } + + if (nbytes == 0) + return 1; + + memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); + + if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) { + if (!padlock_cfb_encrypt(out_arg, in_arg, cdata, chunk)) + return 0; + nbytes -= chunk; + } + + if (nbytes) { + unsigned char *ivp = cdata->iv; + + out_arg += chunk; + in_arg += chunk; + EVP_CIPHER_CTX_set_num(ctx, nbytes); + if (cdata->cword.b.encdec) { + cdata->cword.b.encdec = 0; + padlock_reload_key(); + padlock_aes_block(ivp, ivp, cdata); + cdata->cword.b.encdec = 1; + padlock_reload_key(); + while (nbytes) { + unsigned char c = *(in_arg++); + *(out_arg++) = c ^ *ivp; + *(ivp++) = c, nbytes--; + } + } else { + padlock_reload_key(); + padlock_aes_block(ivp, ivp, cdata); + padlock_reload_key(); + while (nbytes) { + *ivp = *(out_arg++) = *(in_arg++) ^ *ivp; + ivp++, nbytes--; + } + } + } + + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); + + return 1; +} + +static int +padlock_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); + size_t chunk; + + /* + * ctx->num is maintained in byte-oriented modes, such as CFB and OFB... + */ + if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */ + unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx); + + if (chunk >= AES_BLOCK_SIZE) + return 0; /* bogus value */ + + while (chunk < AES_BLOCK_SIZE && nbytes != 0) { + *(out_arg++) = *(in_arg++) ^ ivp[chunk]; + chunk++, nbytes--; + } + + EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE); + } + + if (nbytes == 0) + return 1; + + memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); + + if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) { + if (!padlock_ofb_encrypt(out_arg, in_arg, cdata, chunk)) + return 0; + nbytes -= chunk; + } + + if (nbytes) { + unsigned char *ivp = cdata->iv; + + out_arg += chunk; + in_arg += chunk; + EVP_CIPHER_CTX_set_num(ctx, nbytes); + padlock_reload_key(); /* empirically found */ + padlock_aes_block(ivp, ivp, cdata); + padlock_reload_key(); /* empirically found */ + while (nbytes) { + *(out_arg++) = *(in_arg++) ^ *ivp; + ivp++, nbytes--; + } + } + + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); + + return 1; +} + +static void padlock_ctr32_encrypt_glue(const unsigned char *in, + unsigned char *out, size_t blocks, + struct padlock_cipher_data *ctx, + const unsigned char *ivec) +{ + memcpy(ctx->iv, ivec, AES_BLOCK_SIZE); + padlock_ctr32_encrypt(out, in, ctx, AES_BLOCK_SIZE * blocks); +} + +static int +padlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); + unsigned int num = EVP_CIPHER_CTX_num(ctx); + + CRYPTO_ctr128_encrypt_ctr32(in_arg, out_arg, nbytes, + cdata, EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_buf_noconst(ctx), &num, + (ctr128_f) padlock_ctr32_encrypt_glue); + + EVP_CIPHER_CTX_set_num(ctx, (size_t)num); + return 1; +} + +# define EVP_CIPHER_block_size_ECB AES_BLOCK_SIZE +# define EVP_CIPHER_block_size_CBC AES_BLOCK_SIZE +# define EVP_CIPHER_block_size_OFB 1 +# define EVP_CIPHER_block_size_CFB 1 +# define EVP_CIPHER_block_size_CTR 1 + +/* + * Declaring so many ciphers by hand would be a pain. Instead introduce a bit + * of preprocessor magic :-) + */ +# define DECLARE_AES_EVP(ksize,lmode,umode) \ +static EVP_CIPHER *_hidden_aes_##ksize##_##lmode = NULL; \ +static const EVP_CIPHER *padlock_aes_##ksize##_##lmode(void) \ +{ \ + if (_hidden_aes_##ksize##_##lmode == NULL \ + && ((_hidden_aes_##ksize##_##lmode = \ + EVP_CIPHER_meth_new(NID_aes_##ksize##_##lmode, \ + EVP_CIPHER_block_size_##umode, \ + AES_KEY_SIZE_##ksize)) == NULL \ + || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_##ksize##_##lmode, \ + AES_BLOCK_SIZE) \ + || !EVP_CIPHER_meth_set_flags(_hidden_aes_##ksize##_##lmode, \ + 0 | EVP_CIPH_##umode##_MODE) \ + || !EVP_CIPHER_meth_set_init(_hidden_aes_##ksize##_##lmode, \ + padlock_aes_init_key) \ + || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_##ksize##_##lmode, \ + padlock_##lmode##_cipher) \ + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_##ksize##_##lmode, \ + sizeof(struct padlock_cipher_data) + 16) \ + || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_##ksize##_##lmode, \ + EVP_CIPHER_set_asn1_iv) \ + || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_##ksize##_##lmode, \ + EVP_CIPHER_get_asn1_iv))) { \ + EVP_CIPHER_meth_free(_hidden_aes_##ksize##_##lmode); \ + _hidden_aes_##ksize##_##lmode = NULL; \ + } \ + return _hidden_aes_##ksize##_##lmode; \ +} + +DECLARE_AES_EVP(128, ecb, ECB) +DECLARE_AES_EVP(128, cbc, CBC) +DECLARE_AES_EVP(128, cfb, CFB) +DECLARE_AES_EVP(128, ofb, OFB) +DECLARE_AES_EVP(128, ctr, CTR) + +DECLARE_AES_EVP(192, ecb, ECB) +DECLARE_AES_EVP(192, cbc, CBC) +DECLARE_AES_EVP(192, cfb, CFB) +DECLARE_AES_EVP(192, ofb, OFB) +DECLARE_AES_EVP(192, ctr, CTR) + +DECLARE_AES_EVP(256, ecb, ECB) +DECLARE_AES_EVP(256, cbc, CBC) +DECLARE_AES_EVP(256, cfb, CFB) +DECLARE_AES_EVP(256, ofb, OFB) +DECLARE_AES_EVP(256, ctr, CTR) + +static int +padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, + int nid) +{ + /* No specific cipher => return a list of supported nids ... */ + if (!cipher) { + *nids = padlock_cipher_nids; + return padlock_cipher_nids_num; + } + + /* ... or the requested "cipher" otherwise */ + switch (nid) { + case NID_aes_128_ecb: + *cipher = padlock_aes_128_ecb(); + break; + case NID_aes_128_cbc: + *cipher = padlock_aes_128_cbc(); + break; + case NID_aes_128_cfb: + *cipher = padlock_aes_128_cfb(); + break; + case NID_aes_128_ofb: + *cipher = padlock_aes_128_ofb(); + break; + case NID_aes_128_ctr: + *cipher = padlock_aes_128_ctr(); + break; + + case NID_aes_192_ecb: + *cipher = padlock_aes_192_ecb(); + break; + case NID_aes_192_cbc: + *cipher = padlock_aes_192_cbc(); + break; + case NID_aes_192_cfb: + *cipher = padlock_aes_192_cfb(); + break; + case NID_aes_192_ofb: + *cipher = padlock_aes_192_ofb(); + break; + case NID_aes_192_ctr: + *cipher = padlock_aes_192_ctr(); + break; + + case NID_aes_256_ecb: + *cipher = padlock_aes_256_ecb(); + break; + case NID_aes_256_cbc: + *cipher = padlock_aes_256_cbc(); + break; + case NID_aes_256_cfb: + *cipher = padlock_aes_256_cfb(); + break; + case NID_aes_256_ofb: + *cipher = padlock_aes_256_ofb(); + break; + case NID_aes_256_ctr: + *cipher = padlock_aes_256_ctr(); + break; + + default: + /* Sorry, we don't support this NID */ + *cipher = NULL; + return 0; + } + + return 1; +} + +/* Prepare the encryption key for PadLock usage */ +static int +padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + struct padlock_cipher_data *cdata; + int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8; + unsigned long mode = EVP_CIPHER_CTX_mode(ctx); + + if (key == NULL) + return 0; /* ERROR */ + + cdata = ALIGNED_CIPHER_DATA(ctx); + memset(cdata, 0, sizeof(*cdata)); + + /* Prepare Control word. */ + if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE) + cdata->cword.b.encdec = 0; + else + cdata->cword.b.encdec = (EVP_CIPHER_CTX_encrypting(ctx) == 0); + cdata->cword.b.rounds = 10 + (key_len - 128) / 32; + cdata->cword.b.ksize = (key_len - 128) / 64; + + switch (key_len) { + case 128: + /* + * PadLock can generate an extended key for AES128 in hardware + */ + memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128); + cdata->cword.b.keygen = 0; + break; + + case 192: + case 256: + /* + * Generate an extended AES key in software. Needed for AES192/AES256 + */ + /* + * Well, the above applies to Stepping 8 CPUs and is listed as + * hardware errata. They most likely will fix it at some point and + * then a check for stepping would be due here. + */ + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) + AES_set_decrypt_key(key, key_len, &cdata->ks); + else + AES_set_encrypt_key(key, key_len, &cdata->ks); +# ifndef AES_ASM + /* + * OpenSSL C functions use byte-swapped extended key. + */ + padlock_key_bswap(&cdata->ks); +# endif + cdata->cword.b.keygen = 1; + break; + + default: + /* ERROR */ + return 0; + } + + /* + * This is done to cover for cases when user reuses the + * context for new key. The catch is that if we don't do + * this, padlock_eas_cipher might proceed with old key... + */ + padlock_reload_key(); + + return 1; +} + +/* ===== Random Number Generator ===== */ +/* + * This code is not engaged. The reason is that it does not comply + * with recommendations for VIA RNG usage for secure applications + * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it + * provide meaningful error control... + */ +/* + * Wrapper that provides an interface between the API and the raw PadLock + * RNG + */ +static int padlock_rand_bytes(unsigned char *output, int count) +{ + unsigned int eax, buf; + + while (count >= 8) { + eax = padlock_xstore(output, 0); + if (!(eax & (1 << 6))) + return 0; /* RNG disabled */ + /* this ---vv--- covers DC bias, Raw Bits and String Filter */ + if (eax & (0x1F << 10)) + return 0; + if ((eax & 0x1F) == 0) + continue; /* no data, retry... */ + if ((eax & 0x1F) != 8) + return 0; /* fatal failure... */ + output += 8; + count -= 8; + } + while (count > 0) { + eax = padlock_xstore(&buf, 3); + if (!(eax & (1 << 6))) + return 0; /* RNG disabled */ + /* this ---vv--- covers DC bias, Raw Bits and String Filter */ + if (eax & (0x1F << 10)) + return 0; + if ((eax & 0x1F) == 0) + continue; /* no data, retry... */ + if ((eax & 0x1F) != 1) + return 0; /* fatal failure... */ + *output++ = (unsigned char)buf; + count--; + } + OPENSSL_cleanse(&buf, sizeof(buf)); + + return 1; +} + +/* Dummy but necessary function */ +static int padlock_rand_status(void) +{ + return 1; +} + +/* Prepare structure for registration */ +static RAND_METHOD padlock_rand = { + NULL, /* seed */ + padlock_rand_bytes, /* bytes */ + NULL, /* cleanup */ + NULL, /* add */ + padlock_rand_bytes, /* pseudorand */ + padlock_rand_status, /* rand status */ +}; + +# endif /* COMPILE_HW_PADLOCK */ +# endif /* !OPENSSL_NO_HW_PADLOCK */ +#endif /* !OPENSSL_NO_HW */ + +#if defined(OPENSSL_NO_HW) || defined(OPENSSL_NO_HW_PADLOCK) \ + || !defined(COMPILE_HW_PADLOCK) +# ifndef OPENSSL_NO_DYNAMIC_ENGINE +OPENSSL_EXPORT + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); +OPENSSL_EXPORT + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) +{ + return 0; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() +# endif +#endif -- cgit v1.2.3