1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include "ppport.h"
6
7 #ifndef bytes_from_utf8
8
9 /* 5.6.0 has UTF-8 scalars, but lacks the utility bytes_from_utf8() */
10
11 static U8 *
bytes_from_utf8(U8 * orig,STRLEN * len_p,bool * is_utf8_p)12 bytes_from_utf8(U8 *orig, STRLEN *len_p, bool *is_utf8_p)
13 {
14 STRLEN orig_len = *len_p;
15 U8 *orig_end = orig + orig_len;
16 STRLEN new_len = orig_len;
17 U8 *new;
18 U8 *p, *q;
19 if(!*is_utf8_p)
20 return orig;
21 for(p = orig; p != orig_end; ) {
22 U8 fb = *p++, sb;
23 if(fb <= 0x7f)
24 continue;
25 if(p == orig_end || !(fb >= 0xc2 && fb <= 0xc3))
26 return orig;
27 sb = *p++;
28 if(!(sb >= 0x80 && sb <= 0xbf))
29 return orig;
30 new_len--;
31 }
32 if(new_len == orig_len) {
33 *is_utf8_p = 0;
34 return orig;
35 }
36 Newz(0, new, new_len+1, U8);
37 for(p = orig, q = new; p != orig_end; ) {
38 U8 fb = *p++;
39 *q++ = fb <= 0x7f ? fb : ((fb & 0x03) << 6) | (*p++ & 0x3f);
40 }
41 *q = 0;
42 *len_p = new_len;
43 *is_utf8_p = 0;
44 return new;
45 }
46
47 #endif /* !bytes_from_utf8 */
48
49 #include <./fcrypt/fcrypt.h>
50
51 static void
sv_to_octets(U8 ** octets_p,STRLEN * len_p,bool * must_free_p,SV * sv)52 sv_to_octets(U8 **octets_p, STRLEN *len_p, bool *must_free_p, SV *sv)
53 {
54 U8 *in_str = SvPV(sv, *len_p);
55 bool is_utf8 = !!SvUTF8(sv);
56 *octets_p = bytes_from_utf8(in_str, len_p, &is_utf8);
57 if(is_utf8)
58 croak("input must contain only octets");
59 *must_free_p = *octets_p != in_str;
60 }
61
62 static void
sv_to_cblock(des_cblock block,SV * in_block)63 sv_to_cblock(des_cblock block, SV *in_block)
64 {
65 U8 *in_octets;
66 STRLEN in_len;
67 bool must_free;
68 sv_to_octets(&in_octets, &in_len, &must_free, in_block);
69 if(in_len != 8)
70 croak("data block must be eight octets long");
71 memcpy(block, in_octets, 8);
72 if(must_free)
73 Safefree(in_octets);
74 }
75
76 MODULE = Crypt::UnixCrypt_XS PACKAGE = Crypt::UnixCrypt_XS
77
78 char *
79 crypt( password, salt )
80 SV *password
81 SV *salt
82 CODE:
83 STRLEN password_len, salt_len;
84 U8 *password_octets, *salt_octets;
85 bool password_tofree, salt_tofree;
86 char outbuf[21];
87 sv_to_octets(&password_octets, &password_len, &password_tofree, password);
88 sv_to_octets(&salt_octets, &salt_len, &salt_tofree, salt);
89 des_fcrypt((char *)password_octets, password_len,
90 (char *)salt_octets, salt_len, outbuf);
91 if(password_tofree)
92 Safefree(password_octets);
93 if(salt_tofree)
94 Safefree(salt_octets);
95 RETVAL = outbuf;
96 OUTPUT:
97 RETVAL
98
99 SV *
100 crypt_rounds( password, nrounds, saltnum, in_block )
101 SV *password
102 unsigned long nrounds
103 unsigned long saltnum
104 SV *in_block
105 CODE:
106 STRLEN password_len;
107 U8 *password_octets;
108 bool password_tofree;
109 des_cblock key, block;
110 sv_to_octets(&password_octets, &password_len, &password_tofree, password);
111 sv_to_cblock(block, in_block);
112 trad_password_to_key(key, (char *)password_octets, password_len);
113 if(password_tofree)
114 Safefree(password_octets);
115 crypt_rounds(key, nrounds, saltnum, block);
116 RETVAL = newSVpvn(block, 8);
117 OUTPUT:
118 RETVAL
119
120 SV *
121 fold_password( password )
122 SV *password
123 CODE:
124 STRLEN password_len;
125 U8 *password_octets;
126 bool password_tofree;
127 des_cblock key;
128 int i;
129 sv_to_octets(&password_octets, &password_len, &password_tofree, password);
130 ext_password_to_key(key, (char *)password_octets, password_len);
131 if(password_tofree)
132 Safefree(password_octets);
133 for(i=0; i<8; i++)
134 key[i] = (key[i] & 0xfe) >> 1;
135 RETVAL = newSVpvn(key, 8);
136 OUTPUT:
137 RETVAL
138
139 SV *
140 base64_to_block( base64 )
141 SV *base64
142 CODE:
143 STRLEN base64_len;
144 U8 *base64_octets;
145 bool base64_tofree;
146 des_cblock block;
147 sv_to_octets(&base64_octets, &base64_len, &base64_tofree, base64);
148 if(base64_len != 11)
149 croak("data block in base 64 must be eleven characters long");
150 base64_to_block(block, (char *)base64_octets);
151 if(base64_tofree)
152 Safefree(base64_octets);
153 RETVAL = newSVpvn(block, 8);
154 OUTPUT:
155 RETVAL
156
157 char *
158 block_to_base64( in_block )
159 SV *in_block
160 CODE:
161 des_cblock block;
162 char base64[12];
163 sv_to_cblock(block, in_block);
164 block_to_base64(block, base64);
165 RETVAL = base64;
166 OUTPUT:
167 RETVAL
168
169 unsigned long
170 base64_to_int24( base64 )
171 SV *base64
172 CODE:
173 STRLEN base64_len;
174 U8 *base64_octets;
175 bool base64_tofree;
176 sv_to_octets(&base64_octets, &base64_len, &base64_tofree, base64);
177 if(base64_len != 4)
178 croak("24-bit integer in base 64 must be four characters long");
179 RETVAL = base64_to_int24((char *)base64_octets);
180 if(base64_tofree)
181 Safefree(base64_octets);
182 OUTPUT:
183 RETVAL
184
185 char *
186 int24_to_base64( val )
187 unsigned long val;
188 CODE:
189 char base64[5];
190 int24_to_base64(val, base64);
191 RETVAL = base64;
192 OUTPUT:
193 RETVAL
194
195 unsigned long
196 base64_to_int12( base64 )
197 SV *base64
198 CODE:
199 STRLEN base64_len;
200 U8 *base64_octets;
201 bool base64_tofree;
202 sv_to_octets(&base64_octets, &base64_len, &base64_tofree, base64);
203 if(base64_len != 2)
204 croak("12-bit integer in base 64 must be two characters long");
205 RETVAL = base64_to_int12((char *)base64_octets);
206 if(base64_tofree)
207 Safefree(base64_octets);
208 OUTPUT:
209 RETVAL
210
211 char *
212 int12_to_base64( val )
213 unsigned long val;
214 CODE:
215 char base64[3];
216 int12_to_base64(val, base64);
217 RETVAL = base64;
218 OUTPUT:
219 RETVAL
220