diff options
author | Michael Niedermayer | 2013-01-15 15:56:12 +0100 |
---|---|---|
committer | Michael Niedermayer | 2013-01-15 15:57:33 +0100 |
commit | e7e0186eeb0a0aa1e2ca805b97eb60cbd14e0567 (patch) | |
tree | b19a7ab7351615a21aa0ac7d57c7a486f7318e5b /libavutil/hmac.c | |
parent | e074fe2962df5a43ac41f26b2180094057600cc5 (diff) | |
parent | ab2ad8bd56882c0ea160b154e8b836eb71abc49d (diff) |
Merge commit 'ab2ad8bd56882c0ea160b154e8b836eb71abc49d'
* commit 'ab2ad8bd56882c0ea160b154e8b836eb71abc49d':
lavf: Add functions for SRTP decryption/encryption
lavu: Add an API for calculating HMAC (RFC 2104)
Conflicts:
doc/APIchanges
libavutil/version.h
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavutil/hmac.c')
-rw-r--r-- | libavutil/hmac.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/libavutil/hmac.c b/libavutil/hmac.c new file mode 100644 index 0000000000..1520148246 --- /dev/null +++ b/libavutil/hmac.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2012 Martin Storsjo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <string.h> + +#include "hmac.h" +#include "md5.h" +#include "sha.h" +#include "mem.h" + +#define MAX_HASHLEN 20 +#define MAX_BLOCKLEN 64 + +struct AVHMAC { + void *hash; + int blocklen, hashlen; + void (*final)(void*, uint8_t*); + void (*update)(void*, const uint8_t*, int len); + void (*init)(void*); + uint8_t key[MAX_BLOCKLEN]; + int keylen; +}; + +static void sha1_init(void *ctx) +{ + av_sha_init(ctx, 160); +} + +AVHMAC *av_hmac_alloc(enum AVHMACType type) +{ + AVHMAC *c = av_mallocz(sizeof(*c)); + if (!c) + return NULL; + switch (type) { + case AV_HMAC_MD5: + c->blocklen = 64; + c->hashlen = 16; + c->init = av_md5_init; + c->update = av_md5_update; + c->final = av_md5_final; + c->hash = av_md5_alloc(); + break; + case AV_HMAC_SHA1: + c->blocklen = 64; + c->hashlen = 20; + c->init = sha1_init; + c->update = av_sha_update; + c->final = av_sha_final; + c->hash = av_sha_alloc(); + break; + default: + av_free(c); + return NULL; + } + if (!c->hash) { + av_free(c); + return NULL; + } + return c; +} + +void av_hmac_free(AVHMAC *c) +{ + if (!c) + return; + av_free(c->hash); + av_free(c); +} + +void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen) +{ + int i; + uint8_t block[MAX_BLOCKLEN]; + if (keylen > c->blocklen) { + c->init(c->hash); + c->update(c->hash, key, keylen); + c->final(c->hash, c->key); + c->keylen = c->hashlen; + } else { + memcpy(c->key, key, keylen); + c->keylen = keylen; + } + c->init(c->hash); + for (i = 0; i < c->keylen; i++) + block[i] = c->key[i] ^ 0x36; + for (i = c->keylen; i < c->blocklen; i++) + block[i] = 0x36; + c->update(c->hash, block, c->blocklen); +} + +void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len) +{ + c->update(c->hash, data, len); +} + +int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen) +{ + uint8_t block[MAX_BLOCKLEN]; + int i; + if (outlen < c->hashlen) + return AVERROR(EINVAL); + c->final(c->hash, out); + c->init(c->hash); + for (i = 0; i < c->keylen; i++) + block[i] = c->key[i] ^ 0x5C; + for (i = c->keylen; i < c->blocklen; i++) + block[i] = 0x5C; + c->update(c->hash, block, c->blocklen); + c->update(c->hash, out, c->hashlen); + c->final(c->hash, out); + return c->hashlen; +} + +int av_hmac_calc(AVHMAC *c, const uint8_t *data, unsigned int len, + const uint8_t *key, unsigned int keylen, + uint8_t *out, unsigned int outlen) +{ + av_hmac_init(c, key, keylen); + av_hmac_update(c, data, len); + return av_hmac_final(c, out, outlen); +} |