diff options
author | Bryan Ischo <bryan@ischo.com> | 2008-08-21 05:49:54 +0000 |
---|---|---|
committer | Bryan Ischo <bryan@ischo.com> | 2008-08-21 05:49:54 +0000 |
commit | 9c5615b7752f5e344040ca4669931d7b1aca75df (patch) | |
tree | 9e1f02e4767e6b7e0f738210741396e3bd816f55 /src | |
parent | af16c4d1a3a79d51ba1c1ea661d958eed65c15a3 (diff) | |
download | ceph-libs3-9c5615b7752f5e344040ca4669931d7b1aca75df.tar.gz |
* Implement custom HMAC_SHA1 and thus eliminate all direct dependency on
openssl/GnuTLS/any other cryptographic library
Diffstat (limited to 'src')
-rw-r--r-- | src/crypt.c | 275 | ||||
-rw-r--r-- | src/general.c | 102 | ||||
-rw-r--r-- | src/request.c | 17 |
3 files changed, 284 insertions, 110 deletions
diff --git a/src/crypt.c b/src/crypt.c new file mode 100644 index 0000000..6b22248 --- /dev/null +++ b/src/crypt.c @@ -0,0 +1,275 @@ +/** ************************************************************************** + * crypt.c + * + * Copyright 2008 Bryan Ischo <bryan@ischo.com> + * + * This file is part of libs3. + * + * libs3 is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, version 3 of the License. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of this library and its programs with the + * OpenSSL library, and distribute linked combinations including the two. + * + * libs3 is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License version 3 + * along with libs3, in a file named COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + ************************************************************************** **/ + +#include <stdint.h> +#include <string.h> +#include "crypt.h" + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +#define blk0L(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \ + | (rol(block->l[i], 8) & 0x00FF00FF)) + +#define blk0B(i) (block->l[i]) + +#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ + block->l[(i + 8) & 15] ^ \ + block->l[(i + 2) & 15] ^ \ + block->l[i & 15], 1)) + +#define RL(v, w, x, y, z, i) \ + z += ((w & (x ^ y)) ^ y) + blk0L(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define RB(v, w, x, y, z, i) \ + z += ((w & (x ^ y)) ^ y) + blk0B(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R1(v, w, x, y, z, i) \ + z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R2(v, w, x, y, z, i) \ + z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ + w = rol(w, 30); +#define R3(v, w, x, y, z, i) \ + z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ + w = rol(w, 30); +#define R4(v, w, x, y, z, i) \ + z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ + w = rol(w, 30); + +#define RLA(i) RL(a, b, c, d, e, i) +#define RLB(i) RL(b, c, d, e, a, i) +#define RLC(i) RL(c, d, e, a, b, i) +#define RLD(i) RL(d, e, a, b, c, i) +#define RLE(i) RL(e, a, b, c, d, i) + +#define RBA(i) RB(a, b, c, d, e, i) +#define RBB(i) RB(b, c, d, e, a, i) +#define RBC(i) RB(c, d, e, a, b, i) +#define RBD(i) RB(d, e, a, b, c, i) +#define RBE(i) RB(e, a, b, c, d, i) + +#define R1A(i) R1(a, b, c, d, e, i) +#define R1B(i) R1(b, c, d, e, a, i) +#define R1C(i) R1(c, d, e, a, b, i) +#define R1D(i) R1(d, e, a, b, c, i) +#define R1E(i) R1(e, a, b, c, d, i) + +#define R2A(i) R2(a, b, c, d, e, i) +#define R2B(i) R2(b, c, d, e, a, i) +#define R2C(i) R2(c, d, e, a, b, i) +#define R2D(i) R2(d, e, a, b, c, i) +#define R2E(i) R2(e, a, b, c, d, i) + +#define R3A(i) R3(a, b, c, d, e, i) +#define R3B(i) R3(b, c, d, e, a, i) +#define R3C(i) R3(c, d, e, a, b, i) +#define R3D(i) R3(d, e, a, b, c, i) +#define R3E(i) R3(e, a, b, c, d, i) + +#define R4A(i) R4(a, b, c, d, e, i) +#define R4B(i) R4(b, c, d, e, a, i) +#define R4C(i) R4(c, d, e, a, b, i) +#define R4D(i) R4(d, e, a, b, c, i) +#define R4E(i) R4(e, a, b, c, d, i) + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +static void SHA1_Transform(uint32_t state[5], const unsigned char buffer[64]) +{ + unsigned long a, b, c, d, e; + + typedef union { + unsigned char c[64]; + uint32_t l[16]; + } u; + + static unsigned char w[64]; + u *block = (u *) w; + + memcpy(block, buffer, 64); + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + static unsigned int endianness_indicator = 0x1; + if (((unsigned char *) &endianness_indicator)[0]) { + RLA( 0); RLE( 1); RLD( 2); RLC( 3); RLB( 4); + RLA( 5); RLE( 6); RLD( 7); RLC( 8); RLB( 9); + RLA(10); RLE(11); RLD(12); RLC(13); RLB(14); RLA(15); + } + else { + RBA( 0); RBE( 1); RBD( 2); RBC( 3); RBB( 4); + RBA( 5); RBE( 6); RBD( 7); RBC( 8); RBB( 9); + RBA(10); RBE(11); RBD(12); RBC(13); RBB(14); RBA(15); + } + R1E(16); R1D(17); R1C(18); R1B(19); R2A(20); + R2E(21); R2D(22); R2C(23); R2B(24); R2A(25); + R2E(26); R2D(27); R2C(28); R2B(29); R2A(30); + R2E(31); R2D(32); R2C(33); R2B(34); R2A(35); + R2E(36); R2D(37); R2C(38); R2B(39); R3A(40); + R3E(41); R3D(42); R3C(43); R3B(44); R3A(45); + R3E(46); R3D(47); R3C(48); R3B(49); R3A(50); + R3E(51); R3D(52); R3C(53); R3B(54); R3A(55); + R3E(56); R3D(57); R3C(58); R3B(59); R4A(60); + R4E(61); R4D(62); R4C(63); R4B(64); R4A(65); + R4E(66); R4D(67); R4C(68); R4B(69); R4A(70); + R4E(71); R4D(72); R4C(73); R4B(74); R4A(75); + R4E(76); R4D(77); R4C(78); R4B(79); + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; +} + + +typedef struct +{ + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} sha1ctx; + + +static void SHA1_Init(sha1ctx *context) +{ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +static void SHA1_Update(sha1ctx *context, const unsigned char *data, + unsigned int len) +{ + unsigned int i, j; + + j = (context->count[0] >> 3) & 63; + + if ((context->count[0] += len << 3) < (len << 3)) { + context->count[1]++; + } + + context->count[1] += (len >> 29); + + if ((j + len) > 63) { + memcpy(&(context->buffer[j]), data, (i = 64 - j)); + SHA1_Transform(context->state, context->buffer); + for ( ; (i + 63) < len; i += 64) { + SHA1_Transform(context->state, &(data[i])); + } + j = 0; + } + else { + i = 0; + } + + memcpy(&(context->buffer[j]), &(data[i]), len - i); +} + + +static void SHA1_Final(unsigned char digest[20], sha1ctx *context) +{ + unsigned long i; + unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char) + ((context->count[(i >= 4 ? 0 : 1)] >> + ((3 - (i & 3)) * 8)) & 255); + } + + SHA1_Update(context, (unsigned char *) "\200", 1); + + while ((context->count[0] & 504) != 448) { + SHA1_Update(context, (unsigned char *) "\0", 1); + } + + SHA1_Update(context, finalcount, 8); + + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(&finalcount, 0, 8); + + SHA1_Transform(context->state, context->buffer); +} + + +// HMAC-SHA-1: +// +// K - is key padded with zeros to 512 bits +// m - is message +// OPAD - 0x5c5c5c... +// IPAD - 0x363636... +// +// HMAC(K,m) = SHA1((K ^ OPAD) . SHA1((K ^ IPAD) . m)) +void HMAC_SHA1(unsigned char hmac[20], const unsigned char *key, int key_len, + const unsigned char *message, int message_len) +{ + unsigned char kopad[64], kipad[64]; + int i; + + if (key_len > 64) { + key_len = 64; + } + + for (i = 0; i < key_len; i++) { + kopad[i] = key[i] ^ 0x5c; + kipad[i] = key[i] ^ 0x36; + } + + for ( ; i < 64; i++) { + kopad[i] = 0 ^ 0x5c; + kipad[i] = 0 ^ 0x36; + } + + unsigned char digest[20]; + + sha1ctx context; + + SHA1_Init(&context); + SHA1_Update(&context, kipad, 64); + SHA1_Update(&context, message, message_len); + SHA1_Final(digest, &context); + + SHA1_Init(&context); + SHA1_Update(&context, kopad, 64); + SHA1_Update(&context, digest, 20); + SHA1_Final(hmac, &context); +} diff --git a/src/general.c b/src/general.c index 9904e5a..a9645f0 100644 --- a/src/general.c +++ b/src/general.c @@ -25,13 +25,6 @@ ************************************************************************** **/ #include <ctype.h> -#include <openssl/crypto.h> -#define OPENSSL_THREAD_DEFINES -#include <openssl/opensslconf.h> -#ifndef OPENSSL_THREADS -#error "Threading support required in OpenSSL library, but not provided" -#endif -#include <pthread.h> #include <string.h> #include "request.h" #include "simplexml.h" @@ -39,104 +32,13 @@ static int initializeCountG = 0; -typedef pthread_mutex_t CRYPTO_dynlock_value; - -static pthread_mutex_t *pLocksG; - - -static unsigned long id_callback() -{ - return (unsigned long) pthread_self(); -} - - -static void locking_callback(int mode, int index, const char *file, int line) -{ - if (mode & CRYPTO_LOCK) { - pthread_mutex_lock(&(pLocksG[index])); - } - else { - pthread_mutex_unlock(&(pLocksG[index])); - } -} - - -static struct CRYPTO_dynlock_value *dynlock_create(const char *file, int line) -{ - pthread_mutex_t *ret = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); - pthread_mutex_init(ret, 0); - return (struct CRYPTO_dynlock_value *) ret; -} - - -static void dynlock_lock(int mode, struct CRYPTO_dynlock_value *pLock, - const char *file, int line) -{ - if (mode & CRYPTO_LOCK) { - pthread_mutex_lock((pthread_mutex_t *) pLock); - } - else { - pthread_mutex_unlock((pthread_mutex_t *) pLock); - } -} - - -static void dynlock_destroy(struct CRYPTO_dynlock_value *pLock, - const char *file, int line) -{ - pthread_mutex_destroy((pthread_mutex_t *) pLock); - free(pLock); -} - - -static void deinitialize_locks() -{ - CRYPTO_set_dynlock_destroy_callback(NULL); - CRYPTO_set_dynlock_lock_callback(NULL); - CRYPTO_set_dynlock_create_callback(NULL); - CRYPTO_set_locking_callback(NULL); - CRYPTO_set_id_callback(NULL); - - int count = CRYPTO_num_locks(); - for (int i = 0; i < count; i++) { - pthread_mutex_destroy(&(pLocksG[i])); - } - - free(pLocksG); -} - - S3Status S3_initialize(const char *userAgentInfo, int flags) { if (initializeCountG++) { return S3StatusOK; } - /* As required by the openssl library for thread support */ - int count = CRYPTO_num_locks(), i; - - if (!(pLocksG = - (pthread_mutex_t *) malloc(count * sizeof(pthread_mutex_t)))) { - return S3StatusOutOfMemory; - } - - for (i = 0; i < count; i++) { - pthread_mutex_init(&(pLocksG[i]), 0); - } - - CRYPTO_set_id_callback(&id_callback); - CRYPTO_set_locking_callback(&locking_callback); - CRYPTO_set_dynlock_create_callback(dynlock_create); - CRYPTO_set_dynlock_lock_callback(dynlock_lock); - CRYPTO_set_dynlock_destroy_callback(dynlock_destroy); - - S3Status status = request_api_initialize(userAgentInfo, flags); - if (status != S3StatusOK) { - deinitialize_locks(); - return status; - } - - return S3StatusOK; + return request_api_initialize(userAgentInfo, flags); } @@ -147,8 +49,6 @@ void S3_deinitialize() } request_api_deinitialize(); - - deinitialize_locks(); } const char *S3_get_status_name(S3Status status) diff --git a/src/request.c b/src/request.c index 293c97a..2affa04 100644 --- a/src/request.c +++ b/src/request.c @@ -25,11 +25,11 @@ ************************************************************************** **/ #include <ctype.h> -#include <openssl/hmac.h> #include <pthread.h> #include <stdlib.h> #include <string.h> #include <sys/utsname.h> +#include "crypt.h" #include "request.h" #include "request_context.h" #include "response_headers_handler.h" @@ -706,17 +706,16 @@ static S3Status compose_auth_header(const RequestParams *params, signbuf_append("%s", values->canonicalizedResource); // Generate an HMAC-SHA-1 of the signbuf + unsigned char hmac[20]; - unsigned int md_len; - unsigned char md[EVP_MAX_MD_SIZE]; - - HMAC(EVP_sha1(), params->secretAccessKey, strlen(params->secretAccessKey), - (unsigned char *) signbuf, len, md, &md_len); + HMAC_SHA1(hmac, (unsigned char *) params->secretAccessKey, + strlen(params->secretAccessKey), + (unsigned char *) signbuf, len); // Now base-64 encode the results - unsigned char b64[((md_len + 1) * 4) / 3]; - int b64Len = base64Encode(md, md_len, b64); - + unsigned char b64[((20 + 1) * 4) / 3]; + int b64Len = base64Encode(hmac, 20, b64); + snprintf(values->authorizationHeader, sizeof(values->authorizationHeader), "Authorization: AWS %s:%.*s", params->accessKeyId, b64Len, b64); |