updated mailing address of the FSF
[OpenSRF.git] / src / libopensrf / osrf_digest.c
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or
5  *  (at your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *  GNU General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright (C) 2009 Jason J.A. Stephenson <jason@sigio.com>
17  * Extensively modified by Scott McKellar <scott@esilibrary.com>
18  * Copyright 2009 Equinox Software Inc.
19  */
20
21 /**
22         @file osrf_digest.c
23         @brief Routines to calculate SHA1 and MD5 digests of strings.
24 */
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <gnutls/gnutls.h>
29 #include "opensrf/utils.h"
30 #include "opensrf/osrf_digest.h"
31
32 static void format_hex( char* buf, const unsigned char* s, size_t n );
33
34 /**
35         @brief Calculate an SHA1 digest for a specified string.
36         @param result Pointer to an osrfSHA1Buffer to receive the result.
37         @param str Pointer to a nul-terminated string to be digested.
38 */
39 void osrf_sha1_digest( osrfSHA1Buffer* result, const char *str ) {
40         if( !result )
41                 return;
42
43         result->hex[0] = '\0';
44
45         if( str ) {
46                 size_t out_size = sizeof( result->binary ); /* SHA1 is 160 bits output. */
47
48                 gnutls_datum_t in;
49                 in.data = (unsigned char*) str;
50                 in.size = strlen( str );
51                 if( gnutls_fingerprint( GNUTLS_DIG_SHA1, &in, result->binary, &out_size )
52                                 == GNUTLS_E_SUCCESS ) {
53                         format_hex( result->hex, result->binary, out_size );
54                 }
55         }
56 }
57
58 /**
59         @brief Calculate an SHA1 digest for a formatted string.
60         @param result Pointer to an osrfSHA1Buffer to receive the result.
61         @param str Pointer to a printf-style format string.  Subsequent arguments, if any, are
62         formatted and inserted into the string to be digested.
63 */
64 void osrf_sha1_digest_fmt( osrfSHA1Buffer* result, const char* str, ... ) {
65         if( str ) {
66                 VA_LIST_TO_STRING( str );
67                 osrf_sha1_digest( result, VA_BUF );
68         } else if( result )
69                 result->hex[0] = '\0';
70 }
71
72 /**
73         @brief Calculate an MD5 digest for a specified string.
74         @param result Pointer to an osrfMD5Buffer to receive the result.
75         @param str Pointer to a nul-terminated string to be digested.
76 */
77 void osrf_md5_digest( osrfMD5Buffer* result, const char *str )  {
78         if( !result )
79                 return;
80
81         result->hex[0] = '\0';
82
83         if( str ) {
84                 size_t out_size = sizeof( result->binary ); /* MD5 is 128 bits output. */
85
86                 gnutls_datum_t in;
87                 in.data = (unsigned char*) str;
88                 in.size = strlen( str );
89                 if( gnutls_fingerprint( GNUTLS_DIG_MD5, &in, result->binary, &out_size )
90                                   == GNUTLS_E_SUCCESS ) {
91                         format_hex( result->hex, result->binary, out_size );
92                 }
93         }
94 }
95
96 /**
97         @brief Calculate an MD5 digest for a formatted string.
98         @param result Pointer to an osrfMD5Buffer to receive the result.
99         @param str Pointer to a printf-style format string.  Subsequent arguments, if any, are
100         formatted and inserted into the string to be digested.
101 */
102 void osrf_md5_digest_fmt( osrfMD5Buffer* result, const char* str, ... ) {
103         if( str ) {
104                 VA_LIST_TO_STRING( str );
105                 osrf_md5_digest( result, VA_BUF );
106         } else if( result )
107                 result->hex[0] = '\0';
108 }
109
110 /**
111         @brief Translate a series of bytes to the corresponding hexadecimal representation.
112         @param buf Pointer to the buffer that will receive the output hex characters.
113         @param s Pointer to the input characters to be translated.
114         @param n How many input characters to translate.
115
116         The calling code is responsible for providing a large enough output buffer.  It should
117         be twice as large as the buffer to be translated, plus one for a terminal nul.
118 */
119 static void format_hex( char* buf, const unsigned char* s, size_t n ) {
120         int i;
121         for( i = 0; i < n; ++i ) {
122                 unsigned char c = s[i];
123
124                 // Format high nybble
125                 unsigned char fc = ( c >> 4 ) & 0x0F;
126                 fc += (fc > 9) ? 'a' - 10 : '0';
127                 *buf++ = fc;
128
129                 // Format low nybble
130                 fc = c & 0x0F;
131                 fc += (fc > 9) ? 'a' - 10 : '0';
132                 *buf++ = fc;
133         }
134         *buf = '\0';
135 }