summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBryan Ischo <bryan@ischo.com>2008-08-21 05:49:54 +0000
committerBryan Ischo <bryan@ischo.com>2008-08-21 05:49:54 +0000
commit9c5615b7752f5e344040ca4669931d7b1aca75df (patch)
tree9e1f02e4767e6b7e0f738210741396e3bd816f55 /src
parentaf16c4d1a3a79d51ba1c1ea661d958eed65c15a3 (diff)
downloadceph-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.c275
-rw-r--r--src/general.c102
-rw-r--r--src/request.c17
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);