Release 1.25.0 -- Buddy Idle Time, RTF
[siplcs.git] / src / core / sipe-digest-nss.c
blobf54bf8c16749c9b96d7915f89902c54cd2dddfe7
1 /**
2 * @file sipe-digest-nss.c
4 * pidgin-sipe
6 * Copyright (C) 2011-2016 SIPE Project <http://sipe.sourceforge.net/>
7 * Copyright (C) 2010 pier11 <pier11@operamail.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /**
25 * Digest routines implementation based on NSS.
26 * Includes: SHA1, MD5, HMAC_SHA_1, HMAC_MD5
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
32 #include "glib.h"
34 #include "nss.h"
36 * Work around a compiler error in NSS 3.13.x. Let's hope they fix it for
37 * 3.14.x. See also: https://bugzilla.mozilla.org/show_bug.cgi?id=702090
39 #if (NSS_VMAJOR == 3) && (NSS_VMINOR == 13)
40 #define __GNUC_MINOR __GNUC_MINOR__
41 #endif
42 #include "pk11pub.h"
44 #include "sipe-digest.h"
45 #if !(defined(HAVE_GSSAPI_ONLY) || defined(HAVE_SSPI))
46 #include "md4.h"
47 #endif
50 /* PRIVATE methods */
52 static PK11Context *sipe_digest_ctx_create(const SECOidTag algorithm)
54 PK11Context *context = PK11_CreateDigestContext(algorithm);
55 PK11_DigestBegin(context);
56 return(context);
59 static PK11Context*
60 sipe_digest_hmac_ctx_create(CK_MECHANISM_TYPE hmacMech, const guchar *key, gsize key_length)
62 PK11SlotInfo* slot;
63 SECItem keyItem;
64 SECItem noParams;
65 PK11SymKey* SymKey;
66 PK11Context* DigestContext;
68 /* For key */
69 slot = PK11_GetBestSlot(hmacMech, NULL);
71 keyItem.type = siBuffer;
72 keyItem.data = (unsigned char *)key;
73 keyItem.len = key_length;
75 SymKey = PK11_ImportSymKey(slot, hmacMech, PK11_OriginUnwrap, CKA_SIGN, &keyItem, NULL);
77 /* Parameter for crypto context */
78 noParams.type = siBuffer;
79 noParams.data = NULL;
80 noParams.len = 0;
82 DigestContext = PK11_CreateContextBySymKey(hmacMech, CKA_SIGN, SymKey, &noParams);
84 PK11_DigestBegin(DigestContext);
86 PK11_FreeSymKey(SymKey);
87 PK11_FreeSlot(slot);
89 return DigestContext;
92 static void sipe_digest_ctx_append(PK11Context* DigestContext, const guchar *data, gsize data_length)
94 PK11_DigestOp(DigestContext, data, data_length);
97 static void sipe_digest_ctx_digest(PK11Context* DigestContext, guchar *digest, gsize digest_length)
99 unsigned int len;
101 PK11_DigestFinal(DigestContext, digest, &len, digest_length);
104 static void sipe_digest_ctx_destroy(PK11Context* DigestContext)
106 PK11_DestroyContext(DigestContext, PR_TRUE);
109 static void sipe_digest(const SECOidTag algorithm,
110 const guchar *data, gsize data_length,
111 guchar *digest, gsize digest_length)
113 void *DigestContext;
115 DigestContext = sipe_digest_ctx_create(algorithm);
116 sipe_digest_ctx_append(DigestContext, data, data_length);
117 sipe_digest_ctx_digest(DigestContext, digest, digest_length);
118 sipe_digest_ctx_destroy(DigestContext);
121 static void sipe_digest_hmac(CK_MECHANISM_TYPE hmacMech,
122 const guchar *key, gsize key_length,
123 const guchar *data, gsize data_length,
124 guchar *digest, gsize digest_length)
126 void *DigestContext;
128 DigestContext = sipe_digest_hmac_ctx_create(hmacMech, key, key_length);
129 sipe_digest_ctx_append(DigestContext, data, data_length);
130 sipe_digest_ctx_digest(DigestContext, digest, digest_length);
131 sipe_digest_ctx_destroy(DigestContext);
135 /* PUBLIC methods */
137 #if !(defined(HAVE_GSSAPI_ONLY) || defined(HAVE_SSPI))
138 /* One-shot MD4 digest - only used by internal NTLMv2 implementation */
139 void sipe_digest_md4(const guchar *data, gsize length, guchar *digest)
141 /* NSS does not provide MD4 - use Mozilla Firefox implementation */
142 md4sum(data, length, digest);
144 #endif
146 void sipe_digest_md5(const guchar *data, gsize length, guchar *digest)
148 sipe_digest(SEC_OID_MD5, data, length, digest, SIPE_DIGEST_MD5_LENGTH);
151 void sipe_digest_sha1(const guchar *data, gsize length, guchar *digest)
153 sipe_digest(SEC_OID_SHA1, data, length, digest, SIPE_DIGEST_SHA1_LENGTH);
156 void sipe_digest_hmac_md5(const guchar *key, gsize key_length,
157 const guchar *data, gsize data_length,
158 guchar *digest)
160 sipe_digest_hmac(CKM_MD5_HMAC, key, key_length, data, data_length, digest, SIPE_DIGEST_HMAC_MD5_LENGTH);
163 void sipe_digest_hmac_sha1(const guchar *key, gsize key_length,
164 const guchar *data, gsize data_length,
165 guchar *digest)
167 sipe_digest_hmac(CKM_SHA_1_HMAC, key, key_length, data, data_length, digest, SIPE_DIGEST_HMAC_SHA1_LENGTH);
170 /* Stream HMAC(SHA1) digest for file transfer */
171 gpointer sipe_digest_ft_start(const guchar *sha1_digest)
173 /* used only the first 16 bytes of the 20 byte SHA1 digest */
174 return sipe_digest_hmac_ctx_create(CKM_SHA_1_HMAC, sha1_digest, 16);
177 void sipe_digest_ft_update(gpointer context, const guchar *data, gsize length)
179 sipe_digest_ctx_append(context, data, length);
182 void sipe_digest_ft_end(gpointer context, guchar *digest)
184 sipe_digest_ctx_digest(context, digest, SIPE_DIGEST_FILETRANSFER_LENGTH);
187 void sipe_digest_ft_destroy(gpointer context)
189 sipe_digest_ctx_destroy(context);
192 /* Stream digests, e.g. for TLS */
193 gpointer sipe_digest_md5_start(void)
195 return sipe_digest_ctx_create(SEC_OID_MD5);
198 void sipe_digest_md5_update(gpointer context, const guchar *data, gsize length)
200 sipe_digest_ctx_append(context, data, length);
203 void sipe_digest_md5_end(gpointer context, guchar *digest)
205 unsigned int saved_length;
206 /* save context to ensure this function can be called multiple times */
207 guchar *saved = PK11_SaveContextAlloc(context,
208 NULL,
210 &saved_length);
211 sipe_digest_ctx_digest(context, digest, SIPE_DIGEST_MD5_LENGTH);
212 PK11_RestoreContext(context, saved, saved_length);
213 PORT_Free(saved);
216 void sipe_digest_md5_destroy(gpointer context)
218 sipe_digest_ctx_destroy(context);
221 gpointer sipe_digest_sha1_start(void)
223 return sipe_digest_ctx_create(SEC_OID_SHA1);
226 void sipe_digest_sha1_update(gpointer context, const guchar *data, gsize length)
228 sipe_digest_ctx_append(context, data, length);
231 void sipe_digest_sha1_end(gpointer context, guchar *digest)
233 unsigned int saved_length;
234 /* save context to ensure this function can be called multiple times */
235 guchar *saved = PK11_SaveContextAlloc(context,
236 NULL,
238 &saved_length);
239 sipe_digest_ctx_digest(context, digest, SIPE_DIGEST_SHA1_LENGTH);
240 PK11_RestoreContext(context, saved, saved_length);
241 PORT_Free(saved);
244 void sipe_digest_sha1_destroy(gpointer context)
246 sipe_digest_ctx_destroy(context);
250 Local Variables:
251 mode: c
252 c-file-style: "bsd"
253 indent-tabs-mode: t
254 tab-width: 8
255 End: