summaryrefslogtreecommitdiff
path: root/src/plugins/lanplus/lanplus_crypt_impl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/lanplus/lanplus_crypt_impl.c')
-rw-r--r--src/plugins/lanplus/lanplus_crypt_impl.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/src/plugins/lanplus/lanplus_crypt_impl.c b/src/plugins/lanplus/lanplus_crypt_impl.c
new file mode 100644
index 0000000..cde6c54
--- /dev/null
+++ b/src/plugins/lanplus/lanplus_crypt_impl.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "ipmitool/log.h"
+#include "ipmitool/ipmi_constants.h"
+#include "lanplus.h"
+#include "lanplus_crypt_impl.h"
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <assert.h>
+
+
+
+/*
+ * lanplus_seed_prng
+ *
+ * Seed our PRNG with the specified number of bytes from /dev/random
+ *
+ * param bytes specifies the number of bytes to read from /dev/random
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int lanplus_seed_prng(uint32_t bytes)
+{
+ if (! RAND_load_file("/dev/urandom", bytes))
+ return 1;
+ else
+ return 0;
+}
+
+
+
+/*
+ * lanplus_rand
+ *
+ * Generate a random number of the specified size
+ *
+ * param num_bytes [in] is the size of the random number to be
+ * generated
+ * param buffer [out] is where we will place our random number
+ *
+ * return 0 on success
+ * 1 on failure
+ */
+int
+lanplus_rand(uint8_t * buffer, uint32_t num_bytes)
+{
+#undef IPMI_LANPLUS_FAKE_RAND
+#ifdef IPMI_LANPLUS_FAKE_RAND
+
+ /*
+ * This code exists so that we can easily find the generated random number
+ * in the hex dumps.
+ */
+ int i;
+ for (i = 0; i < num_bytes; ++i)
+ buffer[i] = 0x70 | i;
+
+ return 0;
+#else
+ return (! RAND_bytes(buffer, num_bytes));
+#endif
+}
+
+
+
+/*
+ * lanplus_HMAC
+ *
+ * param mac specifies the algorithm to be used, currently only SHA1 is supported
+ * param key is the key used for HMAC generation
+ * param key_len is the lenght of key
+ * param d is the data to be MAC'd
+ * param n is the length of the data at d
+ * param md is the result of the HMAC algorithm
+ * param md_len is the length of md
+ *
+ * returns a pointer to md
+ */
+uint8_t *
+lanplus_HMAC(uint8_t mac,
+ const void *key,
+ int key_len,
+ const uint8_t *d,
+ int n,
+ uint8_t *md,
+ uint32_t *md_len)
+{
+ const EVP_MD *evp_md = NULL;
+
+ if ((mac == IPMI_AUTH_RAKP_HMAC_SHA1) ||
+ (mac == IPMI_INTEGRITY_HMAC_SHA1_96))
+ evp_md = EVP_sha1();
+ else
+ {
+ lprintf(LOG_DEBUG, "Invalid mac type 0x%x in lanplus_HMAC\n", mac);
+ assert(0);
+ }
+
+ return HMAC(evp_md, key, key_len, d, n, md, (unsigned int *)md_len);
+}
+
+
+/*
+ * lanplus_encrypt_aes_cbc_128
+ *
+ * Encrypt with the AES CBC 128 algorithm
+ *
+ * param iv is the 16 byte initialization vector
+ * param key is the 16 byte key used by the AES algorithm
+ * param input is the data to be encrypted
+ * param input_length is the number of bytes to be encrypted. This MUST
+ * be a multiple of the block size, 16.
+ * param output is the encrypted output
+ * param bytes_written is the number of bytes written. This param is set
+ * to 0 on failure, or if 0 bytes were input.
+ */
+void
+lanplus_encrypt_aes_cbc_128(const uint8_t * iv,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint32_t * bytes_written)
+{
+ EVP_CIPHER_CTX ctx;
+ EVP_CIPHER_CTX_init(&ctx);
+ EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+
+ *bytes_written = 0;
+
+ if (input_length == 0)
+ return;
+
+ if (verbose >= 5)
+ {
+ printbuf(iv, 16, "encrypting with this IV");
+ printbuf(key, 16, "encrypting with this key");
+ printbuf(input, input_length, "encrypting this data");
+ }
+
+
+ /*
+ * The default implementation adds a whole block of padding if the input
+ * data is perfectly aligned. We would like to keep that from happening.
+ * We have made a point to have our input perfectly padded.
+ */
+ assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
+
+
+ if(!EVP_EncryptUpdate(&ctx, output, (int *)bytes_written, input, input_length))
+ {
+ /* Error */
+ *bytes_written = 0;
+ return;
+ }
+ else
+ {
+ uint32_t tmplen;
+
+ if(!EVP_EncryptFinal_ex(&ctx, output + *bytes_written, (int *)&tmplen))
+ {
+ *bytes_written = 0;
+ return; /* Error */
+ }
+ else
+ {
+ /* Success */
+ *bytes_written += tmplen;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ }
+ }
+}
+
+
+
+/*
+ * lanplus_decrypt_aes_cbc_128
+ *
+ * Decrypt with the AES CBC 128 algorithm
+ *
+ * param iv is the 16 byte initialization vector
+ * param key is the 16 byte key used by the AES algorithm
+ * param input is the data to be decrypted
+ * param input_length is the number of bytes to be decrypted. This MUST
+ * be a multiple of the block size, 16.
+ * param output is the decrypted output
+ * param bytes_written is the number of bytes written. This param is set
+ * to 0 on failure, or if 0 bytes were input.
+ */
+void
+lanplus_decrypt_aes_cbc_128(const uint8_t * iv,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint32_t * bytes_written)
+{
+ EVP_CIPHER_CTX ctx;
+ EVP_CIPHER_CTX_init(&ctx);
+ EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+
+ if (verbose >= 5)
+ {
+ printbuf(iv, 16, "decrypting with this IV");
+ printbuf(key, 16, "decrypting with this key");
+ printbuf(input, input_length, "decrypting this data");
+ }
+
+
+ *bytes_written = 0;
+
+ if (input_length == 0)
+ return;
+
+ /*
+ * The default implementation adds a whole block of padding if the input
+ * data is perfectly aligned. We would like to keep that from happening.
+ * We have made a point to have our input perfectly padded.
+ */
+ assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
+
+
+ if (!EVP_DecryptUpdate(&ctx, output, (int *)bytes_written, input, input_length))
+ {
+ /* Error */
+ lprintf(LOG_DEBUG, "ERROR: decrypt update failed");
+ *bytes_written = 0;
+ return;
+ }
+ else
+ {
+ uint32_t tmplen;
+
+ if (!EVP_DecryptFinal_ex(&ctx, output + *bytes_written, (int *)&tmplen))
+ {
+ char buffer[1000];
+ ERR_error_string(ERR_get_error(), buffer);
+ lprintf(LOG_DEBUG, "the ERR error %s", buffer);
+ lprintf(LOG_DEBUG, "ERROR: decrypt final failed");
+ *bytes_written = 0;
+ return; /* Error */
+ }
+ else
+ {
+ /* Success */
+ *bytes_written += tmplen;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ }
+ }
+
+ if (verbose >= 5)
+ {
+ lprintf(LOG_DEBUG, "Decrypted %d encrypted bytes", input_length);
+ printbuf(output, *bytes_written, "Decrypted this data");
+ }
+}