talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit e63f8db4c73928a41343fcc027fd85dfc1c4af90
parent b998857198668a5d6b54f96c9ebc54098c2c001b
Author: Andrej Kacian <ticho@claws-mail.org>
Date:   Thu,  7 Apr 2016 14:49:37 +0200

Added PBKDF2 implementation, copied from OpenBSD.

Diffstat:
Msrc/common/Makefile.am | 6++++--
Asrc/common/pkcs5_pbkdf2.c | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/common/pkcs5_pbkdf2.h | 32++++++++++++++++++++++++++++++++
3 files changed, 168 insertions(+), 2 deletions(-)

diff --git a/src/common/Makefile.am b/src/common/Makefile.am @@ -41,7 +41,8 @@ libclawscommon_la_SOURCES = $(arch_sources) \ utils.c \ uuencode.c \ xml.c \ - xmlprops.c + xmlprops.c \ + pkcs5_pbkdf2.c clawscommonincludedir = $(pkgincludedir)/common clawscommoninclude_HEADERS = $(arch_headers) \ @@ -71,7 +72,8 @@ clawscommoninclude_HEADERS = $(arch_headers) \ uuencode.h \ version.h \ xml.h \ - xmlprops.h + xmlprops.h \ + pkcs5_pbkdf2.h AM_CPPFLAGS = \ -I$(top_srcdir)/intl \ diff --git a/src/common/pkcs5_pbkdf2.c b/src/common/pkcs5_pbkdf2.c @@ -0,0 +1,132 @@ +/* pkcs5_pbkdf2.c - Password-Based Key Derivation Function 2 + * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr> + * + * Modifications for Claws Mail are: + * Copyright (c) 2016 the Claws Mail team + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <glib.h> +#include <sys/types.h> + +#include <string.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> + +#define CHECKSUM_BLOCKLEN 64 +/* + * HMAC-SHA-1 (from RFC 2202). + */ +static void +hmac_sha1(const guchar *text, size_t text_len, const guchar *key, + size_t key_len, guchar *digest) +{ + GChecksum *cksum; + gssize digestlen = g_checksum_type_get_length(G_CHECKSUM_SHA1); + gsize outlen; + guchar k_pad[CHECKSUM_BLOCKLEN]; + guchar tk[digestlen]; + gint i; + + if (key_len > CHECKSUM_BLOCKLEN) { + cksum = g_checksum_new(G_CHECKSUM_SHA1); + g_checksum_update(cksum, key, key_len); + outlen = digestlen; + g_checksum_get_digest(cksum, tk, &outlen); + g_checksum_free(cksum); + + key = tk; + key_len = digestlen; + } + + bzero(k_pad, sizeof k_pad); + bcopy(key, k_pad, key_len); + for (i = 0; i < CHECKSUM_BLOCKLEN; i++) + k_pad[i] ^= 0x36; + + cksum = g_checksum_new(G_CHECKSUM_SHA1); + g_checksum_update(cksum, k_pad, CHECKSUM_BLOCKLEN); + g_checksum_update(cksum, text, text_len); + outlen = digestlen; + g_checksum_get_digest(cksum, digest, &outlen); + g_checksum_free(cksum); + + bzero(k_pad, sizeof k_pad); + bcopy(key, k_pad, key_len); + for (i = 0; i < CHECKSUM_BLOCKLEN; i++) + k_pad[i] ^= 0x5c; + + cksum = g_checksum_new(G_CHECKSUM_SHA1); + g_checksum_update(cksum, k_pad, CHECKSUM_BLOCKLEN); + g_checksum_update(cksum, digest, digestlen); + outlen = digestlen; + g_checksum_get_digest(cksum, digest, &outlen); + g_checksum_free(cksum); +} + +#undef CHECKSUM_BLOCKLEN + +/* + * Password-Based Key Derivation Function 2 (PKCS #5 v2.0). + * Code based on IEEE Std 802.11-2007, Annex H.4.2. + */ +gint +pkcs5_pbkdf2(const gchar *pass, size_t pass_len, const guchar *salt, + size_t salt_len, guchar *key, size_t key_len, guint rounds) +{ + gssize digestlen = g_checksum_type_get_length(G_CHECKSUM_SHA1); + guchar *asalt, obuf[digestlen]; + guchar d1[digestlen], d2[digestlen]; + guint i, j; + guint count; + size_t r; + + if (rounds < 1 || key_len == 0) + return -1; + if (salt_len == 0 || salt_len > SIZE_MAX - 4) + return -1; + if ((asalt = malloc(salt_len + 4)) == NULL) + return -1; + + memcpy(asalt, salt, salt_len); + + for (count = 1; key_len > 0; count++) { + asalt[salt_len + 0] = (count >> 24) & 0xff; + asalt[salt_len + 1] = (count >> 16) & 0xff; + asalt[salt_len + 2] = (count >> 8) & 0xff; + asalt[salt_len + 3] = count & 0xff; + hmac_sha1(asalt, salt_len + 4, pass, pass_len, d1); + memcpy(obuf, d1, sizeof(obuf)); + + for (i = 1; i < rounds; i++) { + hmac_sha1(d1, sizeof(d1), pass, pass_len, d2); + memcpy(d1, d2, sizeof(d1)); + for (j = 0; j < sizeof(obuf); j++) + obuf[j] ^= d1[j]; + } + + r = MIN(key_len, digestlen); + memcpy(key, obuf, r); + key += r; + key_len -= r; + }; + bzero(asalt, salt_len + 4); + free(asalt); + bzero(d1, sizeof(d1)); + bzero(d2, sizeof(d2)); + bzero(obuf, sizeof(obuf)); + + return 0; +} diff --git a/src/common/pkcs5_pbkdf2.h b/src/common/pkcs5_pbkdf2.h @@ -0,0 +1,32 @@ +/* + * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 2016 The Claws Mail Team + * + * pkcs5_pbkdf2.h - Password-Based Key Derivation Function 2 + * + * according to the definition of MD5 in RFC 1321 from April 1992. + * NOTE: This is *not* the same file as the one from glibc + * + * This program 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; either version 3, or (at your option) any + * later version. + * + * This program 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 + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __PKCS_PBKDF2_H +#define __PKCS_PBKDF2_H + +/* The output will be placed into memory pointed to by key parameter. + * Memory needs to be pre-allocated with key_len bytes. */ +gint pkcs5_pbkdf2(const gchar *pass, size_t pass_len, const guchar *salt, + size_t salt_len, guchar *key, size_t key_len, guint rounds); + +#endif /* __PKCS_PBKDF2_H */