File Coverage

inc/CryptX_Mac_KMAC.xs.inc
Criterion Covered Total %
statement 100 108 92.5
branch 73 136 53.6
condition n/a
subroutine n/a
pod n/a
total 173 244 70.9


line stmt bran cond sub pod time code
1             MODULE = CryptX PACKAGE = Crypt::Mac::KMAC
2              
3             PROTOTYPES: DISABLE
4              
5             #define CRYPTX_MAC_KMAC_MAX_OUTPUT_LEN 1000000000UL
6              
7             Crypt::Mac::KMAC
8             new(Class, const char * variant, SV * key, SV * cust = NULL)
9             CODE:
10             {
11 6           STRLEN k_len=0, c_len=0;
12 6           unsigned char *k=NULL, *c=NULL;
13             int rv;
14 6           int var = -1;
15              
16 6 50         if (!SvPOK_spec(key)) croak("FATAL: key must be string/buffer scalar");
    50          
    0          
    0          
    0          
17 6           k = (unsigned char *) SvPVbyte(key, k_len);
18 6 100         if (cust && SvOK(cust)) {
    50          
19 2 50         if (!SvPOK_spec(cust)) croak("FATAL: cust must be string/buffer scalar");
    50          
    0          
    0          
    0          
20 2           c = (unsigned char *) SvPVbyte(cust, c_len);
21             }
22              
23 6 100         if (strcmp(variant, "KMAC128") == 0) var = LTC_KMAC128;
24 6 100         if (strcmp(variant, "KMAC256") == 0) var = LTC_KMAC256;
25 6 50         if (strcmp(variant, "KMACXOF128") == 0) var = LTC_KMAC128_XOF;
26 6 50         if (strcmp(variant, "KMACXOF256") == 0) var = LTC_KMAC256_XOF;
27 6 100         if (var == -1) croak("FATAL: unknown KMAC variant '%s'", variant);
28              
29 5           Newz(0, RETVAL, 1, struct cryptx_mac_kmac_struct);
30 5 50         if (!RETVAL) croak("FATAL: Newz failed");
31              
32 5           rv = kmac_init(&RETVAL->state, var, k, (unsigned long)k_len, c, (unsigned long)c_len);
33 5 50         if (rv != CRYPT_OK) {
34 0           Safefree(RETVAL);
35 0           croak("FATAL: kmac_init failed: %s", error_to_string(rv));
36             }
37 5           RETVAL->finalized = 0;
38 5           RETVAL->variant = var;
39             }
40             OUTPUT:
41             RETVAL
42              
43             void
44             DESTROY(Crypt::Mac::KMAC self)
45             CODE:
46             {
47 6           zeromem(&self->state, sizeof(kmac_state));
48 6           Safefree(self);
49             }
50              
51             Crypt::Mac::KMAC
52             clone(Crypt::Mac::KMAC self)
53             CODE:
54 1           Newz(0, RETVAL, 1, struct cryptx_mac_kmac_struct);
55 1 50         if (!RETVAL) croak("FATAL: Newz failed");
56 1           Copy(self, RETVAL, 1, struct cryptx_mac_kmac_struct);
57             OUTPUT:
58             RETVAL
59              
60             void
61             add(Crypt::Mac::KMAC self, ...)
62             PPCODE:
63             {
64             int rv, i;
65             STRLEN in_data_len;
66             unsigned char *in_data;
67              
68 9 100         if (self->finalized) croak("FATAL: MAC object already finalized");
69 16 100         for(i = 1; i < items; i++) {
70 8           in_data = (unsigned char *)SvPVbyte(ST(i), in_data_len);
71 8 50         if (in_data_len > 0) {
72 8           rv = kmac_process(&self->state, in_data, (unsigned long)in_data_len);
73 8 50         if (rv != CRYPT_OK) croak("FATAL: kmac_process failed: %s", error_to_string(rv));
74             }
75             }
76 8 50         XPUSHs(ST(0)); /* return self */
77             }
78              
79             SV *
80             mac(Crypt::Mac::KMAC self, unsigned long out_len)
81             ALIAS:
82             hexmac = 1
83             b64mac = 2
84             b64umac = 3
85             CODE:
86             {
87             unsigned char *mac_buf;
88             unsigned long maclen, outlen;
89             int rv;
90             char *out;
91              
92 7 100         if (self->finalized) croak("FATAL: MAC object already finalized");
93 6 50         if (out_len == 0) croak("FATAL: invalid output length");
94 6 50         if (out_len > CRYPTX_MAC_KMAC_MAX_OUTPUT_LEN) croak("FATAL: output length too large");
95              
96 6           Newz(0, mac_buf, out_len, unsigned char);
97 6 50         if (!mac_buf) croak("FATAL: Newz failed");
98 6           maclen = out_len;
99 6           rv = kmac_done(&self->state, mac_buf, &maclen);
100 6 50         if (rv != CRYPT_OK) {
101 0           Safefree(mac_buf);
102 0           croak("FATAL: kmac_done failed: %s", error_to_string(rv));
103             }
104 6           self->finalized = 1;
105              
106 6 100         if (ix == 0) {
107 1           RETVAL = newSVpvn((char *)mac_buf, maclen);
108             }
109             else {
110             /* worst case base16 -> 2x; base64 -> ~4/3x; allocate 2x + 4 to be safe */
111 5           unsigned long buflen = maclen * 2 + 8;
112 5           Newz(0, out, buflen, char);
113 5 50         if (!out) { Safefree(mac_buf); croak("FATAL: Newz failed"); }
114 5           outlen = buflen;
115 5 50         if (ix == 3) {
116 0           rv = base64url_encode(mac_buf, maclen, out, &outlen);
117 0 0         if (rv != CRYPT_OK) { Safefree(mac_buf); Safefree(out); croak("FATAL: base64url_encode failed: %s", error_to_string(rv)); }
118             }
119 5 50         else if (ix == 2) {
120 0           rv = base64_encode(mac_buf, maclen, out, &outlen);
121 0 0         if (rv != CRYPT_OK) { Safefree(mac_buf); Safefree(out); croak("FATAL: base64_encode failed: %s", error_to_string(rv)); }
122             }
123             else { /* ix == 1 */
124 5           rv = base16_encode(mac_buf, maclen, out, &outlen, 0);
125 5 50         if (rv != CRYPT_OK) { Safefree(mac_buf); Safefree(out); croak("FATAL: base16_encode failed: %s", error_to_string(rv)); }
126             }
127 5           RETVAL = newSVpvn(out, outlen);
128 5           Safefree(out);
129             }
130 6           zeromem(mac_buf, out_len);
131 6           Safefree(mac_buf);
132             }
133             OUTPUT:
134             RETVAL
135              
136             SV *
137             kmac(const char * variant, unsigned long out_len, SV * key, SV * cust, ...)
138             ALIAS:
139             kmac_hex = 1
140             kmac_b64 = 2
141             kmac_b64u = 3
142             CODE:
143             {
144 24           STRLEN inlen, klen, clen=0;
145 24           unsigned char *in, *k, *c=NULL;
146             int rv, i;
147 24           int var = -1;
148             unsigned char *mac_buf;
149             unsigned long maclen, outlen;
150             char *out;
151             kmac_state st;
152              
153 24 50         if (!SvPOK_spec(key)) croak("FATAL: key must be string/buffer scalar");
    50          
    0          
    0          
    0          
154 24           k = (unsigned char *)SvPVbyte(key, klen);
155 24 50         if (SvOK(cust)) {
156 24 50         if (!SvPOK_spec(cust)) croak("FATAL: cust must be string/buffer scalar");
    50          
    0          
    0          
    0          
157 24           c = (unsigned char *)SvPVbyte(cust, clen);
158             }
159              
160 24 100         if (strcmp(variant, "KMAC128") == 0) var = LTC_KMAC128;
161 24 100         if (strcmp(variant, "KMAC256") == 0) var = LTC_KMAC256;
162 24 100         if (strcmp(variant, "KMACXOF128") == 0) var = LTC_KMAC128_XOF;
163 24 100         if (strcmp(variant, "KMACXOF256") == 0) var = LTC_KMAC256_XOF;
164 24 100         if (var == -1) croak("FATAL: unknown KMAC variant '%s'", variant);
165 20 100         if (out_len == 0) croak("FATAL: invalid output length");
166 19 50         if (out_len > CRYPTX_MAC_KMAC_MAX_OUTPUT_LEN) croak("FATAL: output length too large");
167              
168 19           rv = kmac_init(&st, var, k, (unsigned long)klen, c, (unsigned long)clen);
169 19 50         if (rv != CRYPT_OK) croak("FATAL: kmac_init failed: %s", error_to_string(rv));
170 38 100         for (i = 4; i < items; i++) {
171 19           in = (unsigned char *)SvPVbyte(ST(i), inlen);
172 19 100         if (inlen > 0) {
173 18           rv = kmac_process(&st, in, (unsigned long)inlen);
174 18 50         if (rv != CRYPT_OK) { zeromem(&st, sizeof(st)); croak("FATAL: kmac_process failed: %s", error_to_string(rv)); }
175             }
176             }
177 19           Newz(0, mac_buf, out_len, unsigned char);
178 19 50         if (!mac_buf) { zeromem(&st, sizeof(st)); croak("FATAL: Newz failed"); }
179 19           maclen = out_len;
180 19           rv = kmac_done(&st, mac_buf, &maclen);
181 19           zeromem(&st, sizeof(st));
182 19 50         if (rv != CRYPT_OK) { Safefree(mac_buf); croak("FATAL: kmac_done failed: %s", error_to_string(rv)); }
183              
184 19 100         if (ix == 0) {
185 7           RETVAL = newSVpvn((char *)mac_buf, maclen);
186             }
187             else {
188 12           unsigned long buflen = maclen * 2 + 8;
189 12           Newz(0, out, buflen, char);
190 12 50         if (!out) { Safefree(mac_buf); croak("FATAL: Newz failed"); }
191 12           outlen = buflen;
192 12 100         if (ix == 3) {
193 1           rv = base64url_encode(mac_buf, maclen, out, &outlen);
194 1 50         if (rv != CRYPT_OK) { Safefree(mac_buf); Safefree(out); croak("FATAL: base64url_encode failed: %s", error_to_string(rv)); }
195             }
196 11 100         else if (ix == 2) {
197 1           rv = base64_encode(mac_buf, maclen, out, &outlen);
198 1 50         if (rv != CRYPT_OK) { Safefree(mac_buf); Safefree(out); croak("FATAL: base64_encode failed: %s", error_to_string(rv)); }
199             }
200             else { /* ix == 1 */
201 10           rv = base16_encode(mac_buf, maclen, out, &outlen, 0);
202 10 50         if (rv != CRYPT_OK) { Safefree(mac_buf); Safefree(out); croak("FATAL: base16_encode failed: %s", error_to_string(rv)); }
203             }
204 12           RETVAL = newSVpvn(out, outlen);
205 12           Safefree(out);
206             }
207 19           zeromem(mac_buf, out_len);
208 19           Safefree(mac_buf);
209             }
210             OUTPUT:
211             RETVAL