Implemented public SHA1 interface
A number of XEPs require SHA1. Publishing its interface helps user to reduce number of dependencies.
This commit is contained in:
@@ -21,7 +21,7 @@ libstrophe_la_CFLAGS = $(SSL_CFLAGS) $(STROPHE_FLAGS) $(PARSER_CFLAGS)
|
||||
libstrophe_la_LDFLAGS = $(SSL_LIBS) $(PARSER_LIBS) $(RESOLV_LIBS) -no-undefined
|
||||
# Export only public API
|
||||
libstrophe_la_LDFLAGS += -export-symbols-regex '^xmpp_'
|
||||
libstrophe_la_SOURCES = src/auth.c src/conn.c src/ctx.c \
|
||||
libstrophe_la_SOURCES = src/auth.c src/conn.c src/crypto.c src/ctx.c \
|
||||
src/event.c src/handler.c src/hash.c src/jid.c src/md5.c \
|
||||
src/resolver.c src/sasl.c src/scram.c src/sha1.c \
|
||||
src/snprintf.c src/sock.c src/stanza.c src/util.c \
|
||||
|
||||
184
src/crypto.c
Normal file
184
src/crypto.c
Normal file
@@ -0,0 +1,184 @@
|
||||
/* crypto.c
|
||||
* strophe XMPP client library -- public interface for digests, encodings
|
||||
*
|
||||
* Copyright (C) 2016 Dmitry Podgorny <pasis.ua@gmail.com>
|
||||
*
|
||||
* This software is provided AS-IS with no warranty, either express
|
||||
* or implied.
|
||||
*
|
||||
* This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Public interface for digests and encodings used in XEPs.
|
||||
*/
|
||||
|
||||
/** @defgroup Digests Message digests
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h> /* memset, memcpy */
|
||||
|
||||
#include "common.h" /* xmpp_alloc */
|
||||
#include "ostypes.h" /* uint8_t, size_t */
|
||||
#include "sha1.h"
|
||||
#include "snprintf.h" /* xmpp_snprintf */
|
||||
#include "strophe.h" /* xmpp_ctx_t, xmpp_free */
|
||||
|
||||
struct _xmpp_sha1_t {
|
||||
xmpp_ctx_t *xmpp_ctx;
|
||||
SHA1_CTX ctx;
|
||||
uint8_t digest[SHA1_DIGEST_SIZE];
|
||||
};
|
||||
|
||||
static char *digest_to_string(const uint8_t *digest, char *s, size_t len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (len < SHA1_DIGEST_SIZE * 2 + 1)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < SHA1_DIGEST_SIZE; ++i)
|
||||
xmpp_snprintf(s + i * 2, 3, "%02x", digest[i]);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static char *digest_to_string_alloc(xmpp_ctx_t *ctx, const uint8_t *digest)
|
||||
{
|
||||
char *s;
|
||||
size_t slen;
|
||||
|
||||
slen = SHA1_DIGEST_SIZE * 2 + 1;
|
||||
s = xmpp_alloc(ctx, slen);
|
||||
if (s) {
|
||||
s = digest_to_string(digest, s, slen);
|
||||
assert(s != NULL);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/** Compute SHA1 message digest
|
||||
* Returns an allocated string which represents SHA1 message digest in
|
||||
* hexadecimal notation. The string must be freed with xmpp_free().
|
||||
*
|
||||
* @param ctx a Strophe context object
|
||||
* @param data buffer for digest computation
|
||||
* @param len size of the data buffer
|
||||
*
|
||||
* @return an allocated string or NULL on allocation error
|
||||
*
|
||||
* @ingroup Digests
|
||||
*/
|
||||
char *xmpp_sha1(xmpp_ctx_t *ctx, const unsigned char *data, size_t len)
|
||||
{
|
||||
uint8_t digest[SHA1_DIGEST_SIZE];
|
||||
|
||||
crypto_SHA1((const uint8_t *)data, len, digest);
|
||||
return digest_to_string_alloc(ctx, digest);
|
||||
}
|
||||
|
||||
/** Create new SHA1 object
|
||||
*
|
||||
* @param ctx a Strophe context onject
|
||||
*
|
||||
* @return new SHA1 object
|
||||
*
|
||||
* @ingroup Digests
|
||||
*/
|
||||
xmpp_sha1_t *xmpp_sha1_new(xmpp_ctx_t *ctx)
|
||||
{
|
||||
xmpp_sha1_t *sha1;
|
||||
|
||||
sha1 = xmpp_alloc(ctx, sizeof(*sha1));
|
||||
if (sha1) {
|
||||
memset(sha1, 0, sizeof(*sha1));
|
||||
crypto_SHA1_Init(&sha1->ctx);
|
||||
sha1->xmpp_ctx = ctx;
|
||||
}
|
||||
return sha1;
|
||||
}
|
||||
|
||||
/** Destroy SHA1 object
|
||||
*
|
||||
* @param sha1 a SHA1 object
|
||||
*
|
||||
* @ingroup Digests
|
||||
*/
|
||||
void xmpp_sha1_free(xmpp_sha1_t *sha1)
|
||||
{
|
||||
xmpp_free(sha1->xmpp_ctx, sha1);
|
||||
}
|
||||
|
||||
/** Update SHA1 context with the next portion of data
|
||||
* Can be called repeatedly.
|
||||
*
|
||||
* @param sha1 a SHA1 object
|
||||
* @param data pointer to a buffer to be hashed
|
||||
* @param len size of the data buffer
|
||||
*
|
||||
* @ingroup Digests
|
||||
*/
|
||||
void xmpp_sha1_update(xmpp_sha1_t *sha1, const unsigned char *data, size_t len)
|
||||
{
|
||||
crypto_SHA1_Update(&sha1->ctx, data, len);
|
||||
}
|
||||
|
||||
/** Finish SHA1 computation
|
||||
* Don't call xmpp_sha1_update() after this function. Retrieve resulting
|
||||
* message digest with xmpp_sha1_to_string() or xmpp_sha1_to_digest().
|
||||
*
|
||||
* @param sha1 a SHA1 object
|
||||
*
|
||||
* @ingroup Digests
|
||||
*/
|
||||
void xmpp_sha1_final(xmpp_sha1_t *sha1)
|
||||
{
|
||||
crypto_SHA1_Final(&sha1->ctx, sha1->digest);
|
||||
}
|
||||
|
||||
/** Return message digest rendered as a string
|
||||
* Stores the string to a user's buffer and returns the buffer. Call this
|
||||
* function after xmpp_sha1_final().
|
||||
*
|
||||
* @param sha1 a SHA1 object
|
||||
* @param s output string
|
||||
* @param slen size reserved for the string including '\0'
|
||||
*
|
||||
* @return pointer s or NULL if resulting string is bigger than slen bytes
|
||||
*
|
||||
* @ingroup Digests
|
||||
*/
|
||||
char *xmpp_sha1_to_string(xmpp_sha1_t *sha1, char *s, size_t slen)
|
||||
{
|
||||
return digest_to_string(sha1->digest, s, slen);
|
||||
}
|
||||
|
||||
/** Return message digest rendered as a string
|
||||
* Returns an allocated string. Free the string using the Strophe context
|
||||
* which is passed to xmpp_sha1_new(). Call this function after
|
||||
* xmpp_sha1_final().
|
||||
*
|
||||
* @param sha1 a SHA1 object
|
||||
*
|
||||
* @return an allocated string
|
||||
*
|
||||
* @ingroup Digests
|
||||
*/
|
||||
char *xmpp_sha1_to_string_alloc(xmpp_sha1_t *sha1)
|
||||
{
|
||||
return digest_to_string_alloc(sha1->xmpp_ctx, sha1->digest);
|
||||
}
|
||||
|
||||
/** Stores message digest to a user's buffer
|
||||
*
|
||||
* @param sha1 a SHA1 object
|
||||
* @param digest output buffer of XMPP_SHA1_DIGEST_SIZE bytes
|
||||
*
|
||||
* @ingroup Digests
|
||||
*/
|
||||
void xmpp_sha1_to_digest(xmpp_sha1_t *sha1, unsigned char *digest)
|
||||
{
|
||||
assert(SHA1_DIGEST_SIZE == XMPP_SHA1_DIGEST_SIZE);
|
||||
memcpy(digest, sha1->digest, SHA1_DIGEST_SIZE);
|
||||
}
|
||||
19
strophe.h
19
strophe.h
@@ -388,6 +388,25 @@ void xmpp_stop(xmpp_ctx_t *ctx);
|
||||
|
||||
char *xmpp_uuid_gen(xmpp_ctx_t *ctx);
|
||||
|
||||
/* SHA1 */
|
||||
|
||||
/** @def XMPP_SHA1_DIGEST_SIZE
|
||||
* Size of the SHA1 message digest.
|
||||
*/
|
||||
#define XMPP_SHA1_DIGEST_SIZE 20
|
||||
|
||||
typedef struct _xmpp_sha1_t xmpp_sha1_t;
|
||||
|
||||
char *xmpp_sha1(xmpp_ctx_t *ctx, const unsigned char *data, size_t len);
|
||||
|
||||
xmpp_sha1_t *xmpp_sha1_new(xmpp_ctx_t *ctx);
|
||||
void xmpp_sha1_free(xmpp_sha1_t *sha1);
|
||||
void xmpp_sha1_update(xmpp_sha1_t *sha1, const unsigned char *data, size_t len);
|
||||
void xmpp_sha1_final(xmpp_sha1_t *sha1);
|
||||
char *xmpp_sha1_to_string(xmpp_sha1_t *sha1, char *s, size_t slen);
|
||||
char *xmpp_sha1_to_string_alloc(xmpp_sha1_t *sha1);
|
||||
void xmpp_sha1_to_digest(xmpp_sha1_t *sha1, unsigned char *digest);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user