]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libsec/port/sha1.c
libsec: fix memory leaks in seq_decode() and octet_decode() of asn1 parser
[plan9front.git] / sys / src / libsec / port / sha1.c
1 #include "os.h"
2 #include <libsec.h>
3
4 static void encode(uchar*, u32int*, ulong);
5
6 extern void _sha1block(uchar*, ulong, u32int*);
7
8 /*
9  *  we require len to be a multiple of 64 for all but
10  *  the last call.  There must be room in the input buffer
11  *  to pad.
12  */
13 SHA1state*
14 sha1(uchar *p, ulong len, uchar *digest, SHA1state *s)
15 {
16         uchar buf[128];
17         u32int x[16];
18         int i;
19         uchar *e;
20
21         if(s == nil){
22                 s = malloc(sizeof(*s));
23                 if(s == nil)
24                         return nil;
25                 memset(s, 0, sizeof(*s));
26                 s->malloced = 1;
27         }
28
29         if(s->seeded == 0){
30                 /* seed the state, these constants would look nicer big-endian */
31                 s->state[0] = 0x67452301;
32                 s->state[1] = 0xefcdab89;
33                 s->state[2] = 0x98badcfe;
34                 s->state[3] = 0x10325476;
35                 s->state[4] = 0xc3d2e1f0;
36                 s->seeded = 1;
37         }
38
39         /* fill out the partial 64 byte block from previous calls */
40         if(s->blen){
41                 i = 64 - s->blen;
42                 if(len < i)
43                         i = len;
44                 memmove(s->buf + s->blen, p, i);
45                 len -= i;
46                 s->blen += i;
47                 p += i;
48                 if(s->blen == 64){
49                         _sha1block(s->buf, s->blen, s->state);
50                         s->len += s->blen;
51                         s->blen = 0;
52                 }
53         }
54
55         /* do 64 byte blocks */
56         i = len & ~0x3f;
57         if(i){
58                 _sha1block(p, i, s->state);
59                 s->len += i;
60                 len -= i;
61                 p += i;
62         }
63
64         /* save the left overs if not last call */
65         if(digest == 0){
66                 if(len){
67                         memmove(s->buf, p, len);
68                         s->blen += len;
69                 }
70                 return s;
71         }
72
73         /*
74          *  this is the last time through, pad what's left with 0x80,
75          *  0's, and the input count to create a multiple of 64 bytes
76          */
77         if(s->blen){
78                 p = s->buf;
79                 len = s->blen;
80         } else {
81                 memmove(buf, p, len);
82                 p = buf;
83         }
84         s->len += len;
85         e = p + len;
86         if(len < 56)
87                 i = 56 - len;
88         else
89                 i = 120 - len;
90         memset(e, 0, i);
91         *e = 0x80;
92         len += i;
93
94         /* append the count */
95         x[0] = s->len>>29;
96         x[1] = s->len<<3;
97         encode(p+len, x, 8);
98
99         /* digest the last part */
100         _sha1block(p, len+8, s->state);
101         s->len += len+8;
102
103         /* return result and free state */
104         encode(digest, s->state, SHA1dlen);
105         if(s->malloced == 1)
106                 free(s);
107         return nil;
108 }
109
110 /*
111  *      encodes input (ulong) into output (uchar). Assumes len is
112  *      a multiple of 4.
113  */
114 static void
115 encode(uchar *output, u32int *input, ulong len)
116 {
117         u32int x;
118         uchar *e;
119
120         for(e = output + len; output < e;) {
121                 x = *input++;
122                 *output++ = x >> 24;
123                 *output++ = x >> 16;
124                 *output++ = x >> 8;
125                 *output++ = x;
126         }
127 }
128
129 DigestState*
130 hmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
131         DigestState *s)
132 {
133         return hmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen);
134 }