1 /* compat.c - Various compatibility functions
2  * Copyright 2011, 2012 Gergely Nagy <algernon@balabit.hu>
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "config.h"
18 
19 #if WITH_OPENSSL
20 
21 #include "compat.h"
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <openssl/md5.h>
26 
27 struct _GChecksum
28 {
29   GChecksumType type;
30   char hex_digest[33];
31 
32   MD5_CTX context;
33 };
34 
35 GChecksum *
g_checksum_new(GChecksumType checksum_type)36 g_checksum_new (GChecksumType checksum_type)
37 {
38   GChecksum *chk;
39 
40   if (checksum_type != G_CHECKSUM_MD5)
41     {
42       errno = ENOSYS;
43       return NULL;
44     }
45 
46   chk = calloc (1, sizeof (GChecksum));
47   chk->type = checksum_type;
48 
49   MD5_Init (&chk->context);
50 
51   return chk;
52 }
53 
54 void
g_checksum_free(GChecksum * checksum)55 g_checksum_free (GChecksum *checksum)
56 {
57   if (checksum)
58     free (checksum);
59 }
60 
61 void
g_checksum_update(GChecksum * checksum,const unsigned char * data,ssize_t length)62 g_checksum_update (GChecksum *checksum,
63                    const unsigned char *data,
64                    ssize_t length)
65 {
66   size_t l = length;
67 
68   if (!checksum || !data || length == 0)
69     {
70       errno = EINVAL;
71       return;
72     }
73   errno = 0;
74 
75   if (length < 0)
76     l = strlen ((const char *)data);
77 
78   MD5_Update (&checksum->context, (const void *)data, l);
79 }
80 
81 const char *
g_checksum_get_string(GChecksum * checksum)82 g_checksum_get_string (GChecksum *checksum)
83 {
84   unsigned char digest[16];
85   static const char hex[16] =
86     {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
87      'a', 'b', 'c', 'd', 'e', 'f'};
88   int i;
89 
90   if (!checksum)
91     {
92       errno = EINVAL;
93       return NULL;
94     }
95 
96   MD5_Final (digest, &checksum->context);
97 
98   for (i = 0; i < 16; i++)
99     {
100       checksum->hex_digest[2 * i] = hex[(digest[i] & 0xf0) >> 4];
101       checksum->hex_digest[2 * i + 1] = hex[digest[i] & 0x0f];
102     }
103   checksum->hex_digest[32] = '\0';
104 
105   return checksum->hex_digest;
106 }
107 
108 #endif /* WITH_OPENSSL */
109