1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2004-2023 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * This file uses the low level AES and engine functions (which are deprecated
12e1051a39Sopenharmony_ci * for non-internal use) in order to implement the padlock engine AES ciphers.
13e1051a39Sopenharmony_ci */
14e1051a39Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include <stdio.h>
17e1051a39Sopenharmony_ci#include <string.h>
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ci#include <openssl/opensslconf.h>
20e1051a39Sopenharmony_ci#include <openssl/crypto.h>
21e1051a39Sopenharmony_ci#include <openssl/engine.h>
22e1051a39Sopenharmony_ci#include <openssl/evp.h>
23e1051a39Sopenharmony_ci#include <openssl/aes.h>
24e1051a39Sopenharmony_ci#include <openssl/rand.h>
25e1051a39Sopenharmony_ci#include <openssl/err.h>
26e1051a39Sopenharmony_ci#include <openssl/modes.h>
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_PADLOCKENG
29e1051a39Sopenharmony_ci
30e1051a39Sopenharmony_ci/*
31e1051a39Sopenharmony_ci * VIA PadLock AES is available *ONLY* on some x86 CPUs. Not only that it
32e1051a39Sopenharmony_ci * doesn't exist elsewhere, but it even can't be compiled on other platforms!
33e1051a39Sopenharmony_ci */
34e1051a39Sopenharmony_ci
35e1051a39Sopenharmony_ci# undef COMPILE_PADLOCKENG
36e1051a39Sopenharmony_ci# if defined(PADLOCK_ASM)
37e1051a39Sopenharmony_ci#  define COMPILE_PADLOCKENG
38e1051a39Sopenharmony_ci#  ifdef OPENSSL_NO_DYNAMIC_ENGINE
39e1051a39Sopenharmony_cistatic ENGINE *ENGINE_padlock(void);
40e1051a39Sopenharmony_ci#  endif
41e1051a39Sopenharmony_ci# endif
42e1051a39Sopenharmony_ci
43e1051a39Sopenharmony_ci# ifdef OPENSSL_NO_DYNAMIC_ENGINE
44e1051a39Sopenharmony_civoid engine_load_padlock_int(void);
45e1051a39Sopenharmony_civoid engine_load_padlock_int(void)
46e1051a39Sopenharmony_ci{
47e1051a39Sopenharmony_ci/* On non-x86 CPUs it just returns. */
48e1051a39Sopenharmony_ci#  ifdef COMPILE_PADLOCKENG
49e1051a39Sopenharmony_ci    ENGINE *toadd = ENGINE_padlock();
50e1051a39Sopenharmony_ci    if (!toadd)
51e1051a39Sopenharmony_ci        return;
52e1051a39Sopenharmony_ci    ERR_set_mark();
53e1051a39Sopenharmony_ci    ENGINE_add(toadd);
54e1051a39Sopenharmony_ci    /*
55e1051a39Sopenharmony_ci     * If the "add" worked, it gets a structural reference. So either way, we
56e1051a39Sopenharmony_ci     * release our just-created reference.
57e1051a39Sopenharmony_ci     */
58e1051a39Sopenharmony_ci    ENGINE_free(toadd);
59e1051a39Sopenharmony_ci    /*
60e1051a39Sopenharmony_ci     * If the "add" didn't work, it was probably a conflict because it was
61e1051a39Sopenharmony_ci     * already added (eg. someone calling ENGINE_load_blah then calling
62e1051a39Sopenharmony_ci     * ENGINE_load_builtin_engines() perhaps).
63e1051a39Sopenharmony_ci     */
64e1051a39Sopenharmony_ci    ERR_pop_to_mark();
65e1051a39Sopenharmony_ci#  endif
66e1051a39Sopenharmony_ci}
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_ci# endif
69e1051a39Sopenharmony_ci
70e1051a39Sopenharmony_ci# ifdef COMPILE_PADLOCKENG
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_ci/* Function for ENGINE detection and control */
73e1051a39Sopenharmony_cistatic int padlock_available(void);
74e1051a39Sopenharmony_cistatic int padlock_init(ENGINE *e);
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_ci/* RNG Stuff */
77e1051a39Sopenharmony_cistatic RAND_METHOD padlock_rand;
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ci/* Cipher Stuff */
80e1051a39Sopenharmony_cistatic int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
81e1051a39Sopenharmony_ci                           const int **nids, int nid);
82e1051a39Sopenharmony_ci
83e1051a39Sopenharmony_ci/* Engine names */
84e1051a39Sopenharmony_cistatic const char *padlock_id = "padlock";
85e1051a39Sopenharmony_cistatic char padlock_name[100];
86e1051a39Sopenharmony_ci
87e1051a39Sopenharmony_ci/* Available features */
88e1051a39Sopenharmony_cistatic int padlock_use_ace = 0; /* Advanced Cryptography Engine */
89e1051a39Sopenharmony_cistatic int padlock_use_rng = 0; /* Random Number Generator */
90e1051a39Sopenharmony_ci
91e1051a39Sopenharmony_ci/* ===== Engine "management" functions ===== */
92e1051a39Sopenharmony_ci
93e1051a39Sopenharmony_ci/* Prepare the ENGINE structure for registration */
94e1051a39Sopenharmony_cistatic int padlock_bind_helper(ENGINE *e)
95e1051a39Sopenharmony_ci{
96e1051a39Sopenharmony_ci    /* Check available features */
97e1051a39Sopenharmony_ci    padlock_available();
98e1051a39Sopenharmony_ci
99e1051a39Sopenharmony_ci    /*
100e1051a39Sopenharmony_ci     * RNG is currently disabled for reasons discussed in commentary just
101e1051a39Sopenharmony_ci     * before padlock_rand_bytes function.
102e1051a39Sopenharmony_ci     */
103e1051a39Sopenharmony_ci    padlock_use_rng = 0;
104e1051a39Sopenharmony_ci
105e1051a39Sopenharmony_ci    /* Generate a nice engine name with available features */
106e1051a39Sopenharmony_ci    BIO_snprintf(padlock_name, sizeof(padlock_name),
107e1051a39Sopenharmony_ci                 "VIA PadLock (%s, %s)",
108e1051a39Sopenharmony_ci                 padlock_use_rng ? "RNG" : "no-RNG",
109e1051a39Sopenharmony_ci                 padlock_use_ace ? "ACE" : "no-ACE");
110e1051a39Sopenharmony_ci
111e1051a39Sopenharmony_ci    /* Register everything or return with an error */
112e1051a39Sopenharmony_ci    if (!ENGINE_set_id(e, padlock_id) ||
113e1051a39Sopenharmony_ci        !ENGINE_set_name(e, padlock_name) ||
114e1051a39Sopenharmony_ci        !ENGINE_set_init_function(e, padlock_init) ||
115e1051a39Sopenharmony_ci        (padlock_use_ace && !ENGINE_set_ciphers(e, padlock_ciphers)) ||
116e1051a39Sopenharmony_ci        (padlock_use_rng && !ENGINE_set_RAND(e, &padlock_rand))) {
117e1051a39Sopenharmony_ci        return 0;
118e1051a39Sopenharmony_ci    }
119e1051a39Sopenharmony_ci
120e1051a39Sopenharmony_ci    /* Everything looks good */
121e1051a39Sopenharmony_ci    return 1;
122e1051a39Sopenharmony_ci}
123e1051a39Sopenharmony_ci
124e1051a39Sopenharmony_ci#  ifdef OPENSSL_NO_DYNAMIC_ENGINE
125e1051a39Sopenharmony_ci/* Constructor */
126e1051a39Sopenharmony_cistatic ENGINE *ENGINE_padlock(void)
127e1051a39Sopenharmony_ci{
128e1051a39Sopenharmony_ci    ENGINE *eng = ENGINE_new();
129e1051a39Sopenharmony_ci
130e1051a39Sopenharmony_ci    if (eng == NULL) {
131e1051a39Sopenharmony_ci        return NULL;
132e1051a39Sopenharmony_ci    }
133e1051a39Sopenharmony_ci
134e1051a39Sopenharmony_ci    if (!padlock_bind_helper(eng)) {
135e1051a39Sopenharmony_ci        ENGINE_free(eng);
136e1051a39Sopenharmony_ci        return NULL;
137e1051a39Sopenharmony_ci    }
138e1051a39Sopenharmony_ci
139e1051a39Sopenharmony_ci    return eng;
140e1051a39Sopenharmony_ci}
141e1051a39Sopenharmony_ci#  endif
142e1051a39Sopenharmony_ci
143e1051a39Sopenharmony_ci/* Check availability of the engine */
144e1051a39Sopenharmony_cistatic int padlock_init(ENGINE *e)
145e1051a39Sopenharmony_ci{
146e1051a39Sopenharmony_ci    return (padlock_use_rng || padlock_use_ace);
147e1051a39Sopenharmony_ci}
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ci#  ifndef AES_ASM
150e1051a39Sopenharmony_cistatic int padlock_aes_set_encrypt_key(const unsigned char *userKey,
151e1051a39Sopenharmony_ci                                       const int bits,
152e1051a39Sopenharmony_ci                                       AES_KEY *key);
153e1051a39Sopenharmony_cistatic int padlock_aes_set_decrypt_key(const unsigned char *userKey,
154e1051a39Sopenharmony_ci                                       const int bits,
155e1051a39Sopenharmony_ci                                       AES_KEY *key);
156e1051a39Sopenharmony_ci#   define AES_ASM
157e1051a39Sopenharmony_ci#   define AES_set_encrypt_key padlock_aes_set_encrypt_key
158e1051a39Sopenharmony_ci#   define AES_set_decrypt_key padlock_aes_set_decrypt_key
159e1051a39Sopenharmony_ci#   include "../crypto/aes/aes_core.c"
160e1051a39Sopenharmony_ci#  endif
161e1051a39Sopenharmony_ci
162e1051a39Sopenharmony_ci/*
163e1051a39Sopenharmony_ci * This stuff is needed if this ENGINE is being compiled into a
164e1051a39Sopenharmony_ci * self-contained shared-library.
165e1051a39Sopenharmony_ci */
166e1051a39Sopenharmony_ci#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
167e1051a39Sopenharmony_cistatic int padlock_bind_fn(ENGINE *e, const char *id)
168e1051a39Sopenharmony_ci{
169e1051a39Sopenharmony_ci    if (id && (strcmp(id, padlock_id) != 0)) {
170e1051a39Sopenharmony_ci        return 0;
171e1051a39Sopenharmony_ci    }
172e1051a39Sopenharmony_ci
173e1051a39Sopenharmony_ci    if (!padlock_bind_helper(e)) {
174e1051a39Sopenharmony_ci        return 0;
175e1051a39Sopenharmony_ci    }
176e1051a39Sopenharmony_ci
177e1051a39Sopenharmony_ci    return 1;
178e1051a39Sopenharmony_ci}
179e1051a39Sopenharmony_ci
180e1051a39Sopenharmony_ciIMPLEMENT_DYNAMIC_CHECK_FN()
181e1051a39Sopenharmony_ciIMPLEMENT_DYNAMIC_BIND_FN(padlock_bind_fn)
182e1051a39Sopenharmony_ci#  endif                       /* !OPENSSL_NO_DYNAMIC_ENGINE */
183e1051a39Sopenharmony_ci/* ===== Here comes the "real" engine ===== */
184e1051a39Sopenharmony_ci
185e1051a39Sopenharmony_ci/* Some AES-related constants */
186e1051a39Sopenharmony_ci#  define AES_BLOCK_SIZE          16
187e1051a39Sopenharmony_ci#  define AES_KEY_SIZE_128        16
188e1051a39Sopenharmony_ci#  define AES_KEY_SIZE_192        24
189e1051a39Sopenharmony_ci#  define AES_KEY_SIZE_256        32
190e1051a39Sopenharmony_ci    /*
191e1051a39Sopenharmony_ci     * Here we store the status information relevant to the current context.
192e1051a39Sopenharmony_ci     */
193e1051a39Sopenharmony_ci    /*
194e1051a39Sopenharmony_ci     * BIG FAT WARNING: Inline assembler in PADLOCK_XCRYPT_ASM() depends on
195e1051a39Sopenharmony_ci     * the order of items in this structure.  Don't blindly modify, reorder,
196e1051a39Sopenharmony_ci     * etc!
197e1051a39Sopenharmony_ci     */
198e1051a39Sopenharmony_cistruct padlock_cipher_data {
199e1051a39Sopenharmony_ci    unsigned char iv[AES_BLOCK_SIZE]; /* Initialization vector */
200e1051a39Sopenharmony_ci    union {
201e1051a39Sopenharmony_ci        unsigned int pad[4];
202e1051a39Sopenharmony_ci        struct {
203e1051a39Sopenharmony_ci            int rounds:4;
204e1051a39Sopenharmony_ci            int dgst:1;         /* n/a in C3 */
205e1051a39Sopenharmony_ci            int align:1;        /* n/a in C3 */
206e1051a39Sopenharmony_ci            int ciphr:1;        /* n/a in C3 */
207e1051a39Sopenharmony_ci            unsigned int keygen:1;
208e1051a39Sopenharmony_ci            int interm:1;
209e1051a39Sopenharmony_ci            unsigned int encdec:1;
210e1051a39Sopenharmony_ci            int ksize:2;
211e1051a39Sopenharmony_ci        } b;
212e1051a39Sopenharmony_ci    } cword;                    /* Control word */
213e1051a39Sopenharmony_ci    AES_KEY ks;                 /* Encryption key */
214e1051a39Sopenharmony_ci};
215e1051a39Sopenharmony_ci
216e1051a39Sopenharmony_ci/* Interface to assembler module */
217e1051a39Sopenharmony_ciunsigned int padlock_capability(void);
218e1051a39Sopenharmony_civoid padlock_key_bswap(AES_KEY *key);
219e1051a39Sopenharmony_civoid padlock_verify_context(struct padlock_cipher_data *ctx);
220e1051a39Sopenharmony_civoid padlock_reload_key(void);
221e1051a39Sopenharmony_civoid padlock_aes_block(void *out, const void *inp,
222e1051a39Sopenharmony_ci                       struct padlock_cipher_data *ctx);
223e1051a39Sopenharmony_ciint padlock_ecb_encrypt(void *out, const void *inp,
224e1051a39Sopenharmony_ci                        struct padlock_cipher_data *ctx, size_t len);
225e1051a39Sopenharmony_ciint padlock_cbc_encrypt(void *out, const void *inp,
226e1051a39Sopenharmony_ci                        struct padlock_cipher_data *ctx, size_t len);
227e1051a39Sopenharmony_ciint padlock_cfb_encrypt(void *out, const void *inp,
228e1051a39Sopenharmony_ci                        struct padlock_cipher_data *ctx, size_t len);
229e1051a39Sopenharmony_ciint padlock_ofb_encrypt(void *out, const void *inp,
230e1051a39Sopenharmony_ci                        struct padlock_cipher_data *ctx, size_t len);
231e1051a39Sopenharmony_ciint padlock_ctr32_encrypt(void *out, const void *inp,
232e1051a39Sopenharmony_ci                          struct padlock_cipher_data *ctx, size_t len);
233e1051a39Sopenharmony_ciint padlock_xstore(void *out, int edx);
234e1051a39Sopenharmony_civoid padlock_sha1_oneshot(void *ctx, const void *inp, size_t len);
235e1051a39Sopenharmony_civoid padlock_sha1(void *ctx, const void *inp, size_t len);
236e1051a39Sopenharmony_civoid padlock_sha256_oneshot(void *ctx, const void *inp, size_t len);
237e1051a39Sopenharmony_civoid padlock_sha256(void *ctx, const void *inp, size_t len);
238e1051a39Sopenharmony_ci
239e1051a39Sopenharmony_ci/*
240e1051a39Sopenharmony_ci * Load supported features of the CPU to see if the PadLock is available.
241e1051a39Sopenharmony_ci */
242e1051a39Sopenharmony_cistatic int padlock_available(void)
243e1051a39Sopenharmony_ci{
244e1051a39Sopenharmony_ci    unsigned int edx = padlock_capability();
245e1051a39Sopenharmony_ci
246e1051a39Sopenharmony_ci    /* Fill up some flags */
247e1051a39Sopenharmony_ci    padlock_use_ace = ((edx & (0x3 << 6)) == (0x3 << 6));
248e1051a39Sopenharmony_ci    padlock_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2));
249e1051a39Sopenharmony_ci
250e1051a39Sopenharmony_ci    return padlock_use_ace + padlock_use_rng;
251e1051a39Sopenharmony_ci}
252e1051a39Sopenharmony_ci
253e1051a39Sopenharmony_ci/* ===== AES encryption/decryption ===== */
254e1051a39Sopenharmony_ci
255e1051a39Sopenharmony_ci#  if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
256e1051a39Sopenharmony_ci#   define NID_aes_128_cfb NID_aes_128_cfb128
257e1051a39Sopenharmony_ci#  endif
258e1051a39Sopenharmony_ci
259e1051a39Sopenharmony_ci#  if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
260e1051a39Sopenharmony_ci#   define NID_aes_128_ofb NID_aes_128_ofb128
261e1051a39Sopenharmony_ci#  endif
262e1051a39Sopenharmony_ci
263e1051a39Sopenharmony_ci#  if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
264e1051a39Sopenharmony_ci#   define NID_aes_192_cfb NID_aes_192_cfb128
265e1051a39Sopenharmony_ci#  endif
266e1051a39Sopenharmony_ci
267e1051a39Sopenharmony_ci#  if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
268e1051a39Sopenharmony_ci#   define NID_aes_192_ofb NID_aes_192_ofb128
269e1051a39Sopenharmony_ci#  endif
270e1051a39Sopenharmony_ci
271e1051a39Sopenharmony_ci#  if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
272e1051a39Sopenharmony_ci#   define NID_aes_256_cfb NID_aes_256_cfb128
273e1051a39Sopenharmony_ci#  endif
274e1051a39Sopenharmony_ci
275e1051a39Sopenharmony_ci#  if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
276e1051a39Sopenharmony_ci#   define NID_aes_256_ofb NID_aes_256_ofb128
277e1051a39Sopenharmony_ci#  endif
278e1051a39Sopenharmony_ci
279e1051a39Sopenharmony_ci/* List of supported ciphers. */
280e1051a39Sopenharmony_cistatic const int padlock_cipher_nids[] = {
281e1051a39Sopenharmony_ci    NID_aes_128_ecb,
282e1051a39Sopenharmony_ci    NID_aes_128_cbc,
283e1051a39Sopenharmony_ci    NID_aes_128_cfb,
284e1051a39Sopenharmony_ci    NID_aes_128_ofb,
285e1051a39Sopenharmony_ci    NID_aes_128_ctr,
286e1051a39Sopenharmony_ci
287e1051a39Sopenharmony_ci    NID_aes_192_ecb,
288e1051a39Sopenharmony_ci    NID_aes_192_cbc,
289e1051a39Sopenharmony_ci    NID_aes_192_cfb,
290e1051a39Sopenharmony_ci    NID_aes_192_ofb,
291e1051a39Sopenharmony_ci    NID_aes_192_ctr,
292e1051a39Sopenharmony_ci
293e1051a39Sopenharmony_ci    NID_aes_256_ecb,
294e1051a39Sopenharmony_ci    NID_aes_256_cbc,
295e1051a39Sopenharmony_ci    NID_aes_256_cfb,
296e1051a39Sopenharmony_ci    NID_aes_256_ofb,
297e1051a39Sopenharmony_ci    NID_aes_256_ctr
298e1051a39Sopenharmony_ci};
299e1051a39Sopenharmony_ci
300e1051a39Sopenharmony_cistatic int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids) /
301e1051a39Sopenharmony_ci                                      sizeof(padlock_cipher_nids[0]));
302e1051a39Sopenharmony_ci
303e1051a39Sopenharmony_ci/* Function prototypes ... */
304e1051a39Sopenharmony_cistatic int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
305e1051a39Sopenharmony_ci                                const unsigned char *iv, int enc);
306e1051a39Sopenharmony_ci
307e1051a39Sopenharmony_ci#  define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) +         \
308e1051a39Sopenharmony_ci        ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F )      )
309e1051a39Sopenharmony_ci#  define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\
310e1051a39Sopenharmony_ci        NEAREST_ALIGNED(EVP_CIPHER_CTX_get_cipher_data(ctx)))
311e1051a39Sopenharmony_ci
312e1051a39Sopenharmony_cistatic int
313e1051a39Sopenharmony_cipadlock_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
314e1051a39Sopenharmony_ci                   const unsigned char *in_arg, size_t nbytes)
315e1051a39Sopenharmony_ci{
316e1051a39Sopenharmony_ci    return padlock_ecb_encrypt(out_arg, in_arg,
317e1051a39Sopenharmony_ci                               ALIGNED_CIPHER_DATA(ctx), nbytes);
318e1051a39Sopenharmony_ci}
319e1051a39Sopenharmony_ci
320e1051a39Sopenharmony_cistatic int
321e1051a39Sopenharmony_cipadlock_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
322e1051a39Sopenharmony_ci                   const unsigned char *in_arg, size_t nbytes)
323e1051a39Sopenharmony_ci{
324e1051a39Sopenharmony_ci    struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
325e1051a39Sopenharmony_ci    int ret;
326e1051a39Sopenharmony_ci
327e1051a39Sopenharmony_ci    memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
328e1051a39Sopenharmony_ci    if ((ret = padlock_cbc_encrypt(out_arg, in_arg, cdata, nbytes)))
329e1051a39Sopenharmony_ci        memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
330e1051a39Sopenharmony_ci    return ret;
331e1051a39Sopenharmony_ci}
332e1051a39Sopenharmony_ci
333e1051a39Sopenharmony_cistatic int
334e1051a39Sopenharmony_cipadlock_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
335e1051a39Sopenharmony_ci                   const unsigned char *in_arg, size_t nbytes)
336e1051a39Sopenharmony_ci{
337e1051a39Sopenharmony_ci    struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
338e1051a39Sopenharmony_ci    size_t chunk;
339e1051a39Sopenharmony_ci
340e1051a39Sopenharmony_ci    if ((chunk = EVP_CIPHER_CTX_get_num(ctx))) {   /* borrow chunk variable */
341e1051a39Sopenharmony_ci        unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx);
342e1051a39Sopenharmony_ci
343e1051a39Sopenharmony_ci        if (chunk >= AES_BLOCK_SIZE)
344e1051a39Sopenharmony_ci            return 0;           /* bogus value */
345e1051a39Sopenharmony_ci
346e1051a39Sopenharmony_ci        if (EVP_CIPHER_CTX_is_encrypting(ctx))
347e1051a39Sopenharmony_ci            while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
348e1051a39Sopenharmony_ci                ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk];
349e1051a39Sopenharmony_ci                chunk++, nbytes--;
350e1051a39Sopenharmony_ci        } else
351e1051a39Sopenharmony_ci            while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
352e1051a39Sopenharmony_ci                unsigned char c = *(in_arg++);
353e1051a39Sopenharmony_ci                *(out_arg++) = c ^ ivp[chunk];
354e1051a39Sopenharmony_ci                ivp[chunk++] = c, nbytes--;
355e1051a39Sopenharmony_ci            }
356e1051a39Sopenharmony_ci
357e1051a39Sopenharmony_ci        EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE);
358e1051a39Sopenharmony_ci    }
359e1051a39Sopenharmony_ci
360e1051a39Sopenharmony_ci    if (nbytes == 0)
361e1051a39Sopenharmony_ci        return 1;
362e1051a39Sopenharmony_ci
363e1051a39Sopenharmony_ci    memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
364e1051a39Sopenharmony_ci
365e1051a39Sopenharmony_ci    if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) {
366e1051a39Sopenharmony_ci        if (!padlock_cfb_encrypt(out_arg, in_arg, cdata, chunk))
367e1051a39Sopenharmony_ci            return 0;
368e1051a39Sopenharmony_ci        nbytes -= chunk;
369e1051a39Sopenharmony_ci    }
370e1051a39Sopenharmony_ci
371e1051a39Sopenharmony_ci    if (nbytes) {
372e1051a39Sopenharmony_ci        unsigned char *ivp = cdata->iv;
373e1051a39Sopenharmony_ci
374e1051a39Sopenharmony_ci        out_arg += chunk;
375e1051a39Sopenharmony_ci        in_arg += chunk;
376e1051a39Sopenharmony_ci        EVP_CIPHER_CTX_set_num(ctx, nbytes);
377e1051a39Sopenharmony_ci        if (cdata->cword.b.encdec) {
378e1051a39Sopenharmony_ci            cdata->cword.b.encdec = 0;
379e1051a39Sopenharmony_ci            padlock_reload_key();
380e1051a39Sopenharmony_ci            padlock_aes_block(ivp, ivp, cdata);
381e1051a39Sopenharmony_ci            cdata->cword.b.encdec = 1;
382e1051a39Sopenharmony_ci            padlock_reload_key();
383e1051a39Sopenharmony_ci            while (nbytes) {
384e1051a39Sopenharmony_ci                unsigned char c = *(in_arg++);
385e1051a39Sopenharmony_ci                *(out_arg++) = c ^ *ivp;
386e1051a39Sopenharmony_ci                *(ivp++) = c, nbytes--;
387e1051a39Sopenharmony_ci            }
388e1051a39Sopenharmony_ci        } else {
389e1051a39Sopenharmony_ci            padlock_reload_key();
390e1051a39Sopenharmony_ci            padlock_aes_block(ivp, ivp, cdata);
391e1051a39Sopenharmony_ci            padlock_reload_key();
392e1051a39Sopenharmony_ci            while (nbytes) {
393e1051a39Sopenharmony_ci                *ivp = *(out_arg++) = *(in_arg++) ^ *ivp;
394e1051a39Sopenharmony_ci                ivp++, nbytes--;
395e1051a39Sopenharmony_ci            }
396e1051a39Sopenharmony_ci        }
397e1051a39Sopenharmony_ci    }
398e1051a39Sopenharmony_ci
399e1051a39Sopenharmony_ci    memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
400e1051a39Sopenharmony_ci
401e1051a39Sopenharmony_ci    return 1;
402e1051a39Sopenharmony_ci}
403e1051a39Sopenharmony_ci
404e1051a39Sopenharmony_cistatic int
405e1051a39Sopenharmony_cipadlock_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
406e1051a39Sopenharmony_ci                   const unsigned char *in_arg, size_t nbytes)
407e1051a39Sopenharmony_ci{
408e1051a39Sopenharmony_ci    struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
409e1051a39Sopenharmony_ci    size_t chunk;
410e1051a39Sopenharmony_ci
411e1051a39Sopenharmony_ci    /*
412e1051a39Sopenharmony_ci     * ctx->num is maintained in byte-oriented modes, such as CFB and OFB...
413e1051a39Sopenharmony_ci     */
414e1051a39Sopenharmony_ci    if ((chunk = EVP_CIPHER_CTX_get_num(ctx))) {   /* borrow chunk variable */
415e1051a39Sopenharmony_ci        unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx);
416e1051a39Sopenharmony_ci
417e1051a39Sopenharmony_ci        if (chunk >= AES_BLOCK_SIZE)
418e1051a39Sopenharmony_ci            return 0;           /* bogus value */
419e1051a39Sopenharmony_ci
420e1051a39Sopenharmony_ci        while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
421e1051a39Sopenharmony_ci            *(out_arg++) = *(in_arg++) ^ ivp[chunk];
422e1051a39Sopenharmony_ci            chunk++, nbytes--;
423e1051a39Sopenharmony_ci        }
424e1051a39Sopenharmony_ci
425e1051a39Sopenharmony_ci        EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE);
426e1051a39Sopenharmony_ci    }
427e1051a39Sopenharmony_ci
428e1051a39Sopenharmony_ci    if (nbytes == 0)
429e1051a39Sopenharmony_ci        return 1;
430e1051a39Sopenharmony_ci
431e1051a39Sopenharmony_ci    memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
432e1051a39Sopenharmony_ci
433e1051a39Sopenharmony_ci    if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) {
434e1051a39Sopenharmony_ci        if (!padlock_ofb_encrypt(out_arg, in_arg, cdata, chunk))
435e1051a39Sopenharmony_ci            return 0;
436e1051a39Sopenharmony_ci        nbytes -= chunk;
437e1051a39Sopenharmony_ci    }
438e1051a39Sopenharmony_ci
439e1051a39Sopenharmony_ci    if (nbytes) {
440e1051a39Sopenharmony_ci        unsigned char *ivp = cdata->iv;
441e1051a39Sopenharmony_ci
442e1051a39Sopenharmony_ci        out_arg += chunk;
443e1051a39Sopenharmony_ci        in_arg += chunk;
444e1051a39Sopenharmony_ci        EVP_CIPHER_CTX_set_num(ctx, nbytes);
445e1051a39Sopenharmony_ci        padlock_reload_key();   /* empirically found */
446e1051a39Sopenharmony_ci        padlock_aes_block(ivp, ivp, cdata);
447e1051a39Sopenharmony_ci        padlock_reload_key();   /* empirically found */
448e1051a39Sopenharmony_ci        while (nbytes) {
449e1051a39Sopenharmony_ci            *(out_arg++) = *(in_arg++) ^ *ivp;
450e1051a39Sopenharmony_ci            ivp++, nbytes--;
451e1051a39Sopenharmony_ci        }
452e1051a39Sopenharmony_ci    }
453e1051a39Sopenharmony_ci
454e1051a39Sopenharmony_ci    memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
455e1051a39Sopenharmony_ci
456e1051a39Sopenharmony_ci    return 1;
457e1051a39Sopenharmony_ci}
458e1051a39Sopenharmony_ci
459e1051a39Sopenharmony_cistatic void padlock_ctr32_encrypt_glue(const unsigned char *in,
460e1051a39Sopenharmony_ci                                       unsigned char *out, size_t blocks,
461e1051a39Sopenharmony_ci                                       struct padlock_cipher_data *ctx,
462e1051a39Sopenharmony_ci                                       const unsigned char *ivec)
463e1051a39Sopenharmony_ci{
464e1051a39Sopenharmony_ci    memcpy(ctx->iv, ivec, AES_BLOCK_SIZE);
465e1051a39Sopenharmony_ci    padlock_ctr32_encrypt(out, in, ctx, AES_BLOCK_SIZE * blocks);
466e1051a39Sopenharmony_ci}
467e1051a39Sopenharmony_ci
468e1051a39Sopenharmony_cistatic int
469e1051a39Sopenharmony_cipadlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
470e1051a39Sopenharmony_ci                   const unsigned char *in_arg, size_t nbytes)
471e1051a39Sopenharmony_ci{
472e1051a39Sopenharmony_ci    struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
473e1051a39Sopenharmony_ci    int n = EVP_CIPHER_CTX_get_num(ctx);
474e1051a39Sopenharmony_ci    unsigned int num;
475e1051a39Sopenharmony_ci
476e1051a39Sopenharmony_ci    if (n < 0)
477e1051a39Sopenharmony_ci        return 0;
478e1051a39Sopenharmony_ci    num = (unsigned int)n;
479e1051a39Sopenharmony_ci
480e1051a39Sopenharmony_ci    CRYPTO_ctr128_encrypt_ctr32(in_arg, out_arg, nbytes,
481e1051a39Sopenharmony_ci                                cdata, EVP_CIPHER_CTX_iv_noconst(ctx),
482e1051a39Sopenharmony_ci                                EVP_CIPHER_CTX_buf_noconst(ctx), &num,
483e1051a39Sopenharmony_ci                                (ctr128_f) padlock_ctr32_encrypt_glue);
484e1051a39Sopenharmony_ci
485e1051a39Sopenharmony_ci    EVP_CIPHER_CTX_set_num(ctx, (size_t)num);
486e1051a39Sopenharmony_ci    return 1;
487e1051a39Sopenharmony_ci}
488e1051a39Sopenharmony_ci
489e1051a39Sopenharmony_ci#  define EVP_CIPHER_block_size_ECB       AES_BLOCK_SIZE
490e1051a39Sopenharmony_ci#  define EVP_CIPHER_block_size_CBC       AES_BLOCK_SIZE
491e1051a39Sopenharmony_ci#  define EVP_CIPHER_block_size_OFB       1
492e1051a39Sopenharmony_ci#  define EVP_CIPHER_block_size_CFB       1
493e1051a39Sopenharmony_ci#  define EVP_CIPHER_block_size_CTR       1
494e1051a39Sopenharmony_ci
495e1051a39Sopenharmony_ci/*
496e1051a39Sopenharmony_ci * Declaring so many ciphers by hand would be a pain. Instead introduce a bit
497e1051a39Sopenharmony_ci * of preprocessor magic :-)
498e1051a39Sopenharmony_ci */
499e1051a39Sopenharmony_ci#  define DECLARE_AES_EVP(ksize,lmode,umode)      \
500e1051a39Sopenharmony_cistatic EVP_CIPHER *_hidden_aes_##ksize##_##lmode = NULL; \
501e1051a39Sopenharmony_cistatic const EVP_CIPHER *padlock_aes_##ksize##_##lmode(void) \
502e1051a39Sopenharmony_ci{                                                                       \
503e1051a39Sopenharmony_ci    if (_hidden_aes_##ksize##_##lmode == NULL                           \
504e1051a39Sopenharmony_ci        && ((_hidden_aes_##ksize##_##lmode =                            \
505e1051a39Sopenharmony_ci             EVP_CIPHER_meth_new(NID_aes_##ksize##_##lmode,             \
506e1051a39Sopenharmony_ci                                 EVP_CIPHER_block_size_##umode,         \
507e1051a39Sopenharmony_ci                                 AES_KEY_SIZE_##ksize)) == NULL         \
508e1051a39Sopenharmony_ci            || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_##ksize##_##lmode, \
509e1051a39Sopenharmony_ci                                              AES_BLOCK_SIZE)           \
510e1051a39Sopenharmony_ci            || !EVP_CIPHER_meth_set_flags(_hidden_aes_##ksize##_##lmode, \
511e1051a39Sopenharmony_ci                                          0 | EVP_CIPH_##umode##_MODE)  \
512e1051a39Sopenharmony_ci            || !EVP_CIPHER_meth_set_init(_hidden_aes_##ksize##_##lmode, \
513e1051a39Sopenharmony_ci                                         padlock_aes_init_key)          \
514e1051a39Sopenharmony_ci            || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_##ksize##_##lmode, \
515e1051a39Sopenharmony_ci                                              padlock_##lmode##_cipher) \
516e1051a39Sopenharmony_ci            || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_##ksize##_##lmode, \
517e1051a39Sopenharmony_ci                                                  sizeof(struct padlock_cipher_data) + 16) \
518e1051a39Sopenharmony_ci            || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_##ksize##_##lmode, \
519e1051a39Sopenharmony_ci                                                    EVP_CIPHER_set_asn1_iv) \
520e1051a39Sopenharmony_ci            || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_##ksize##_##lmode, \
521e1051a39Sopenharmony_ci                                                    EVP_CIPHER_get_asn1_iv))) { \
522e1051a39Sopenharmony_ci        EVP_CIPHER_meth_free(_hidden_aes_##ksize##_##lmode);            \
523e1051a39Sopenharmony_ci        _hidden_aes_##ksize##_##lmode = NULL;                           \
524e1051a39Sopenharmony_ci    }                                                                   \
525e1051a39Sopenharmony_ci    return _hidden_aes_##ksize##_##lmode;                               \
526e1051a39Sopenharmony_ci}
527e1051a39Sopenharmony_ci
528e1051a39Sopenharmony_ciDECLARE_AES_EVP(128, ecb, ECB)
529e1051a39Sopenharmony_ciDECLARE_AES_EVP(128, cbc, CBC)
530e1051a39Sopenharmony_ciDECLARE_AES_EVP(128, cfb, CFB)
531e1051a39Sopenharmony_ciDECLARE_AES_EVP(128, ofb, OFB)
532e1051a39Sopenharmony_ciDECLARE_AES_EVP(128, ctr, CTR)
533e1051a39Sopenharmony_ci
534e1051a39Sopenharmony_ciDECLARE_AES_EVP(192, ecb, ECB)
535e1051a39Sopenharmony_ciDECLARE_AES_EVP(192, cbc, CBC)
536e1051a39Sopenharmony_ciDECLARE_AES_EVP(192, cfb, CFB)
537e1051a39Sopenharmony_ciDECLARE_AES_EVP(192, ofb, OFB)
538e1051a39Sopenharmony_ciDECLARE_AES_EVP(192, ctr, CTR)
539e1051a39Sopenharmony_ci
540e1051a39Sopenharmony_ciDECLARE_AES_EVP(256, ecb, ECB)
541e1051a39Sopenharmony_ciDECLARE_AES_EVP(256, cbc, CBC)
542e1051a39Sopenharmony_ciDECLARE_AES_EVP(256, cfb, CFB)
543e1051a39Sopenharmony_ciDECLARE_AES_EVP(256, ofb, OFB)
544e1051a39Sopenharmony_ciDECLARE_AES_EVP(256, ctr, CTR)
545e1051a39Sopenharmony_ci
546e1051a39Sopenharmony_cistatic int
547e1051a39Sopenharmony_cipadlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids,
548e1051a39Sopenharmony_ci                int nid)
549e1051a39Sopenharmony_ci{
550e1051a39Sopenharmony_ci    /* No specific cipher => return a list of supported nids ... */
551e1051a39Sopenharmony_ci    if (!cipher) {
552e1051a39Sopenharmony_ci        *nids = padlock_cipher_nids;
553e1051a39Sopenharmony_ci        return padlock_cipher_nids_num;
554e1051a39Sopenharmony_ci    }
555e1051a39Sopenharmony_ci
556e1051a39Sopenharmony_ci    /* ... or the requested "cipher" otherwise */
557e1051a39Sopenharmony_ci    switch (nid) {
558e1051a39Sopenharmony_ci    case NID_aes_128_ecb:
559e1051a39Sopenharmony_ci        *cipher = padlock_aes_128_ecb();
560e1051a39Sopenharmony_ci        break;
561e1051a39Sopenharmony_ci    case NID_aes_128_cbc:
562e1051a39Sopenharmony_ci        *cipher = padlock_aes_128_cbc();
563e1051a39Sopenharmony_ci        break;
564e1051a39Sopenharmony_ci    case NID_aes_128_cfb:
565e1051a39Sopenharmony_ci        *cipher = padlock_aes_128_cfb();
566e1051a39Sopenharmony_ci        break;
567e1051a39Sopenharmony_ci    case NID_aes_128_ofb:
568e1051a39Sopenharmony_ci        *cipher = padlock_aes_128_ofb();
569e1051a39Sopenharmony_ci        break;
570e1051a39Sopenharmony_ci    case NID_aes_128_ctr:
571e1051a39Sopenharmony_ci        *cipher = padlock_aes_128_ctr();
572e1051a39Sopenharmony_ci        break;
573e1051a39Sopenharmony_ci
574e1051a39Sopenharmony_ci    case NID_aes_192_ecb:
575e1051a39Sopenharmony_ci        *cipher = padlock_aes_192_ecb();
576e1051a39Sopenharmony_ci        break;
577e1051a39Sopenharmony_ci    case NID_aes_192_cbc:
578e1051a39Sopenharmony_ci        *cipher = padlock_aes_192_cbc();
579e1051a39Sopenharmony_ci        break;
580e1051a39Sopenharmony_ci    case NID_aes_192_cfb:
581e1051a39Sopenharmony_ci        *cipher = padlock_aes_192_cfb();
582e1051a39Sopenharmony_ci        break;
583e1051a39Sopenharmony_ci    case NID_aes_192_ofb:
584e1051a39Sopenharmony_ci        *cipher = padlock_aes_192_ofb();
585e1051a39Sopenharmony_ci        break;
586e1051a39Sopenharmony_ci    case NID_aes_192_ctr:
587e1051a39Sopenharmony_ci        *cipher = padlock_aes_192_ctr();
588e1051a39Sopenharmony_ci        break;
589e1051a39Sopenharmony_ci
590e1051a39Sopenharmony_ci    case NID_aes_256_ecb:
591e1051a39Sopenharmony_ci        *cipher = padlock_aes_256_ecb();
592e1051a39Sopenharmony_ci        break;
593e1051a39Sopenharmony_ci    case NID_aes_256_cbc:
594e1051a39Sopenharmony_ci        *cipher = padlock_aes_256_cbc();
595e1051a39Sopenharmony_ci        break;
596e1051a39Sopenharmony_ci    case NID_aes_256_cfb:
597e1051a39Sopenharmony_ci        *cipher = padlock_aes_256_cfb();
598e1051a39Sopenharmony_ci        break;
599e1051a39Sopenharmony_ci    case NID_aes_256_ofb:
600e1051a39Sopenharmony_ci        *cipher = padlock_aes_256_ofb();
601e1051a39Sopenharmony_ci        break;
602e1051a39Sopenharmony_ci    case NID_aes_256_ctr:
603e1051a39Sopenharmony_ci        *cipher = padlock_aes_256_ctr();
604e1051a39Sopenharmony_ci        break;
605e1051a39Sopenharmony_ci
606e1051a39Sopenharmony_ci    default:
607e1051a39Sopenharmony_ci        /* Sorry, we don't support this NID */
608e1051a39Sopenharmony_ci        *cipher = NULL;
609e1051a39Sopenharmony_ci        return 0;
610e1051a39Sopenharmony_ci    }
611e1051a39Sopenharmony_ci
612e1051a39Sopenharmony_ci    return 1;
613e1051a39Sopenharmony_ci}
614e1051a39Sopenharmony_ci
615e1051a39Sopenharmony_ci/* Prepare the encryption key for PadLock usage */
616e1051a39Sopenharmony_cistatic int
617e1051a39Sopenharmony_cipadlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
618e1051a39Sopenharmony_ci                     const unsigned char *iv, int enc)
619e1051a39Sopenharmony_ci{
620e1051a39Sopenharmony_ci    struct padlock_cipher_data *cdata;
621e1051a39Sopenharmony_ci    int key_len = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
622e1051a39Sopenharmony_ci    unsigned long mode = EVP_CIPHER_CTX_get_mode(ctx);
623e1051a39Sopenharmony_ci
624e1051a39Sopenharmony_ci    if (key == NULL)
625e1051a39Sopenharmony_ci        return 0;               /* ERROR */
626e1051a39Sopenharmony_ci
627e1051a39Sopenharmony_ci    cdata = ALIGNED_CIPHER_DATA(ctx);
628e1051a39Sopenharmony_ci    memset(cdata, 0, sizeof(*cdata));
629e1051a39Sopenharmony_ci
630e1051a39Sopenharmony_ci    /* Prepare Control word. */
631e1051a39Sopenharmony_ci    if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE)
632e1051a39Sopenharmony_ci        cdata->cword.b.encdec = 0;
633e1051a39Sopenharmony_ci    else
634e1051a39Sopenharmony_ci        cdata->cword.b.encdec = (EVP_CIPHER_CTX_is_encrypting(ctx) == 0);
635e1051a39Sopenharmony_ci    cdata->cword.b.rounds = 10 + (key_len - 128) / 32;
636e1051a39Sopenharmony_ci    cdata->cword.b.ksize = (key_len - 128) / 64;
637e1051a39Sopenharmony_ci
638e1051a39Sopenharmony_ci    switch (key_len) {
639e1051a39Sopenharmony_ci    case 128:
640e1051a39Sopenharmony_ci        /*
641e1051a39Sopenharmony_ci         * PadLock can generate an extended key for AES128 in hardware
642e1051a39Sopenharmony_ci         */
643e1051a39Sopenharmony_ci        memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128);
644e1051a39Sopenharmony_ci        cdata->cword.b.keygen = 0;
645e1051a39Sopenharmony_ci        break;
646e1051a39Sopenharmony_ci
647e1051a39Sopenharmony_ci    case 192:
648e1051a39Sopenharmony_ci    case 256:
649e1051a39Sopenharmony_ci        /*
650e1051a39Sopenharmony_ci         * Generate an extended AES key in software. Needed for AES192/AES256
651e1051a39Sopenharmony_ci         */
652e1051a39Sopenharmony_ci        /*
653e1051a39Sopenharmony_ci         * Well, the above applies to Stepping 8 CPUs and is listed as
654e1051a39Sopenharmony_ci         * hardware errata. They most likely will fix it at some point and
655e1051a39Sopenharmony_ci         * then a check for stepping would be due here.
656e1051a39Sopenharmony_ci         */
657e1051a39Sopenharmony_ci        if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
658e1051a39Sopenharmony_ci            && !enc)
659e1051a39Sopenharmony_ci            AES_set_decrypt_key(key, key_len, &cdata->ks);
660e1051a39Sopenharmony_ci        else
661e1051a39Sopenharmony_ci            AES_set_encrypt_key(key, key_len, &cdata->ks);
662e1051a39Sopenharmony_ci        /*
663e1051a39Sopenharmony_ci         * OpenSSL C functions use byte-swapped extended key.
664e1051a39Sopenharmony_ci         */
665e1051a39Sopenharmony_ci        padlock_key_bswap(&cdata->ks);
666e1051a39Sopenharmony_ci        cdata->cword.b.keygen = 1;
667e1051a39Sopenharmony_ci        break;
668e1051a39Sopenharmony_ci
669e1051a39Sopenharmony_ci    default:
670e1051a39Sopenharmony_ci        /* ERROR */
671e1051a39Sopenharmony_ci        return 0;
672e1051a39Sopenharmony_ci    }
673e1051a39Sopenharmony_ci
674e1051a39Sopenharmony_ci    /*
675e1051a39Sopenharmony_ci     * This is done to cover for cases when user reuses the
676e1051a39Sopenharmony_ci     * context for new key. The catch is that if we don't do
677e1051a39Sopenharmony_ci     * this, padlock_eas_cipher might proceed with old key...
678e1051a39Sopenharmony_ci     */
679e1051a39Sopenharmony_ci    padlock_reload_key();
680e1051a39Sopenharmony_ci
681e1051a39Sopenharmony_ci    return 1;
682e1051a39Sopenharmony_ci}
683e1051a39Sopenharmony_ci
684e1051a39Sopenharmony_ci/* ===== Random Number Generator ===== */
685e1051a39Sopenharmony_ci/*
686e1051a39Sopenharmony_ci * This code is not engaged. The reason is that it does not comply
687e1051a39Sopenharmony_ci * with recommendations for VIA RNG usage for secure applications
688e1051a39Sopenharmony_ci * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it
689e1051a39Sopenharmony_ci * provide meaningful error control...
690e1051a39Sopenharmony_ci */
691e1051a39Sopenharmony_ci/*
692e1051a39Sopenharmony_ci * Wrapper that provides an interface between the API and the raw PadLock
693e1051a39Sopenharmony_ci * RNG
694e1051a39Sopenharmony_ci */
695e1051a39Sopenharmony_cistatic int padlock_rand_bytes(unsigned char *output, int count)
696e1051a39Sopenharmony_ci{
697e1051a39Sopenharmony_ci    unsigned int eax, buf;
698e1051a39Sopenharmony_ci
699e1051a39Sopenharmony_ci    while (count >= 8) {
700e1051a39Sopenharmony_ci        eax = padlock_xstore(output, 0);
701e1051a39Sopenharmony_ci        if (!(eax & (1 << 6)))
702e1051a39Sopenharmony_ci            return 0;           /* RNG disabled */
703e1051a39Sopenharmony_ci        /* this ---vv--- covers DC bias, Raw Bits and String Filter */
704e1051a39Sopenharmony_ci        if (eax & (0x1F << 10))
705e1051a39Sopenharmony_ci            return 0;
706e1051a39Sopenharmony_ci        if ((eax & 0x1F) == 0)
707e1051a39Sopenharmony_ci            continue;           /* no data, retry... */
708e1051a39Sopenharmony_ci        if ((eax & 0x1F) != 8)
709e1051a39Sopenharmony_ci            return 0;           /* fatal failure...  */
710e1051a39Sopenharmony_ci        output += 8;
711e1051a39Sopenharmony_ci        count -= 8;
712e1051a39Sopenharmony_ci    }
713e1051a39Sopenharmony_ci    while (count > 0) {
714e1051a39Sopenharmony_ci        eax = padlock_xstore(&buf, 3);
715e1051a39Sopenharmony_ci        if (!(eax & (1 << 6)))
716e1051a39Sopenharmony_ci            return 0;           /* RNG disabled */
717e1051a39Sopenharmony_ci        /* this ---vv--- covers DC bias, Raw Bits and String Filter */
718e1051a39Sopenharmony_ci        if (eax & (0x1F << 10))
719e1051a39Sopenharmony_ci            return 0;
720e1051a39Sopenharmony_ci        if ((eax & 0x1F) == 0)
721e1051a39Sopenharmony_ci            continue;           /* no data, retry... */
722e1051a39Sopenharmony_ci        if ((eax & 0x1F) != 1)
723e1051a39Sopenharmony_ci            return 0;           /* fatal failure...  */
724e1051a39Sopenharmony_ci        *output++ = (unsigned char)buf;
725e1051a39Sopenharmony_ci        count--;
726e1051a39Sopenharmony_ci    }
727e1051a39Sopenharmony_ci    OPENSSL_cleanse(&buf, sizeof(buf));
728e1051a39Sopenharmony_ci
729e1051a39Sopenharmony_ci    return 1;
730e1051a39Sopenharmony_ci}
731e1051a39Sopenharmony_ci
732e1051a39Sopenharmony_ci/* Dummy but necessary function */
733e1051a39Sopenharmony_cistatic int padlock_rand_status(void)
734e1051a39Sopenharmony_ci{
735e1051a39Sopenharmony_ci    return 1;
736e1051a39Sopenharmony_ci}
737e1051a39Sopenharmony_ci
738e1051a39Sopenharmony_ci/* Prepare structure for registration */
739e1051a39Sopenharmony_cistatic RAND_METHOD padlock_rand = {
740e1051a39Sopenharmony_ci    NULL,                       /* seed */
741e1051a39Sopenharmony_ci    padlock_rand_bytes,         /* bytes */
742e1051a39Sopenharmony_ci    NULL,                       /* cleanup */
743e1051a39Sopenharmony_ci    NULL,                       /* add */
744e1051a39Sopenharmony_ci    padlock_rand_bytes,         /* pseudorand */
745e1051a39Sopenharmony_ci    padlock_rand_status,        /* rand status */
746e1051a39Sopenharmony_ci};
747e1051a39Sopenharmony_ci
748e1051a39Sopenharmony_ci# endif                        /* COMPILE_PADLOCKENG */
749e1051a39Sopenharmony_ci#endif                         /* !OPENSSL_NO_PADLOCKENG */
750e1051a39Sopenharmony_ci
751e1051a39Sopenharmony_ci#if defined(OPENSSL_NO_PADLOCKENG) || !defined(COMPILE_PADLOCKENG)
752e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_DYNAMIC_ENGINE
753e1051a39Sopenharmony_ciOPENSSL_EXPORT
754e1051a39Sopenharmony_ci    int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
755e1051a39Sopenharmony_ciOPENSSL_EXPORT
756e1051a39Sopenharmony_ci    int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns)
757e1051a39Sopenharmony_ci{
758e1051a39Sopenharmony_ci    return 0;
759e1051a39Sopenharmony_ci}
760e1051a39Sopenharmony_ci
761e1051a39Sopenharmony_ciIMPLEMENT_DYNAMIC_CHECK_FN()
762e1051a39Sopenharmony_ci# endif
763e1051a39Sopenharmony_ci#endif
764