Add more asn.1 types.
http-signature/asn1.scm
26 | 26 | make-asn1-type | |
27 | 27 | asn1-type-name | |
28 | 28 | asn1-type-type | |
29 | + | asn1-type-primitive? | |
30 | + | asn1-type-constructed? | |
29 | 31 | asn1-type-parser | |
30 | 32 | asn1-type-producer | |
33 | + | asn1-type-aggregator | |
31 | 34 | ||
32 | 35 | asn1:bool | |
33 | 36 | asn1:null | |
37 | + | asn1:int-bv | |
38 | + | asn1:bitstring | |
39 | + | asn1:octetstring | |
40 | + | asn1:object-identifier | |
34 | 41 | asn1:sequence | |
35 | 42 | ||
36 | 43 | encode-asn1 | |
… | |||
41 | 48 | ;; a DER encoded ASN.1 record, or to produce a DER-encoded ASN.1 record. | |
42 | 49 | ||
43 | 50 | (define-record-type asn1-type | |
44 | - | (make-asn1-type name type parser producer) | |
51 | + | (make-asn1-type name type primitive? constructed? parser producer aggregator) | |
45 | 52 | asn1-type? | |
46 | 53 | (name asn1-type-name) | |
47 | 54 | (type asn1-type-type) | |
55 | + | (primitive? asn1-type-primitive?) | |
56 | + | (constructed? asn1-type-constructed?) | |
48 | 57 | (parser asn1-type-parser) | |
49 | - | (producer asn1-type-producer)) | |
58 | + | (producer asn1-type-producer) | |
59 | + | (aggregator asn1-type-aggregator)) | |
50 | 60 | ||
51 | 61 | (define asn1:bool | |
52 | 62 | (make-asn1-type | |
53 | - | "bool" 1 | |
63 | + | "bool" 1 #t #f | |
54 | 64 | (lambda (bv pos len) | |
55 | 65 | (unless (equal? len 1) | |
56 | 66 | (throw 'invalid-bool-value)) | |
… | |||
59 | 69 | (lambda (value) | |
60 | 70 | (let ((bv (make-bytevector 1))) | |
61 | 71 | (bytevector-u8-set! bv 0 (if value #xff #x00)) | |
62 | - | bv)))) | |
72 | + | bv)) | |
73 | + | (lambda _ (throw 'primitive-type)))) | |
63 | 74 | ||
64 | 75 | (define asn1:null | |
65 | 76 | (make-asn1-type | |
66 | - | "null" 5 | |
77 | + | "null" 5 #t #f | |
67 | 78 | (lambda (bv pos len) | |
68 | 79 | (unless (equal? len 0) | |
69 | 80 | (throw 'invalid-null-value)) | |
70 | 81 | #nil) | |
71 | 82 | (lambda (value) | |
72 | - | (make-bytevector 0)))) | |
83 | + | (make-bytevector 0)) | |
84 | + | (lambda _ (throw 'primitive-type)))) | |
85 | + | ||
86 | + | ;(define asn1:int-int | |
87 | + | ; (make-asn1-type | |
88 | + | ; "int" 2 | |
89 | + | ; (lambda (bv pos len) | |
90 | + | ; (let ((ans (make-bytevector len))) | |
91 | + | ; (bytevector-copy! bv pos ans 0 len) | |
92 | + | ; (let loop ((num 0) (off 0)) | |
93 | + | ; (if (> off len) | |
94 | + | ; num | |
95 | + | ; (loop (+ (* num 256) (bytevector-u8-ref bv off)) | |
96 | + | ; (+ off 1)))))) | |
97 | + | ; (lambda (value) | |
98 | + | ; ()))) | |
99 | + | ||
100 | + | (define asn1:int-bv | |
101 | + | (make-asn1-type | |
102 | + | "int" 2 #t #f | |
103 | + | (lambda (bv pos len) | |
104 | + | (let ((ans (make-bytevector len))) | |
105 | + | (bytevector-copy! bv pos ans 0 len) | |
106 | + | ans)) | |
107 | + | (lambda (value) | |
108 | + | value) | |
109 | + | (lambda _ (throw 'primitive-type)))) | |
110 | + | ||
111 | + | ;(define asn1:enum asn1:int-int) | |
112 | + | ||
113 | + | (define asn1:bitstring | |
114 | + | (make-asn1-type | |
115 | + | "bitstring" 3 #t #t | |
116 | + | (lambda (bv pos len) | |
117 | + | (let ((ans (make-bytevector len))) | |
118 | + | (bytevector-copy! bv pos ans 0 len) | |
119 | + | ans)) | |
120 | + | (lambda (value) | |
121 | + | value) | |
122 | + | (lambda (value) | |
123 | + | (apply bv-append value)))) | |
124 | + | ||
125 | + | (define asn1:octetstring | |
126 | + | (make-asn1-type | |
127 | + | "octetstring" 4 #t #t | |
128 | + | (lambda (bv pos len) | |
129 | + | (let ((ans (make-bytevector len))) | |
130 | + | (bytevector-copy! bv pos ans 0 len) | |
131 | + | ans)) | |
132 | + | (lambda (value) | |
133 | + | value) | |
134 | + | (lambda (value) | |
135 | + | (apply bv-append value)))) | |
136 | + | ||
137 | + | (define asn1:object-identifier | |
138 | + | (make-asn1-type | |
139 | + | "object-identifier" 6 #t #f | |
140 | + | (lambda (bv pos len) | |
141 | + | (when (= len 0) | |
142 | + | (throw 'invalid-object-identifier)) | |
143 | + | (let loop ((len len) (pos pos) (value '()) (new? #t)) | |
144 | + | (if (<= len 0) | |
145 | + | (if (= len 0) | |
146 | + | (let* ((vals (reverse value)) | |
147 | + | (first-identifier (car vals))) | |
148 | + | (append | |
149 | + | (cond | |
150 | + | ((< first-identifier 40) (list 0 (modulo first-identifier 40))) | |
151 | + | ((< first-identifier 80) (list 1 (modulo first-identifier 40))) | |
152 | + | (else (list 2 (- first-identifier 80)))) | |
153 | + | (cdr vals))) | |
154 | + | (throw 'value-too-long)) | |
155 | + | (let* ((val (bytevector-u8-ref bv pos)) | |
156 | + | (cont? (> val #x80)) | |
157 | + | (val (logand #x7f val))) | |
158 | + | (if new? | |
159 | + | (loop (- len 1) (+ pos 1) | |
160 | + | (cons val value) | |
161 | + | (not cont?)) | |
162 | + | (loop (- len 1) (+ pos 1) | |
163 | + | (cons (+ val (* (car value) 128)) (cdr value)) | |
164 | + | (not cont?))))))) | |
165 | + | (lambda (value) | |
166 | + | (match value | |
167 | + | ((x y rest ...) | |
168 | + | (let ((first-byte (+ (* x 40) y))) | |
169 | + | (apply bv-append | |
170 | + | (map | |
171 | + | (lambda (identifier) | |
172 | + | (define (id-len identifier) | |
173 | + | (if (< identifier 128) | |
174 | + | 1 | |
175 | + | (+ 1 (id-len (quotient identifier 128))))) | |
176 | + | (let ((bv (make-bytevector (id-len identifier)))) | |
177 | + | (let loop ((pos (- (bytevector-length bv) 1)) (id identifier)) | |
178 | + | (if (= pos (- (bytevector-length bv) 1)) | |
179 | + | (begin | |
180 | + | (bytevector-u8-set! bv pos (modulo id 128)) | |
181 | + | (loop (- pos 1) (quotient id 128))) | |
182 | + | (if (= pos -1) | |
183 | + | bv | |
184 | + | (begin | |
185 | + | (bytevector-u8-set! bv pos (+ #x80 (modulo id 128))) | |
186 | + | (loop (- pos 1) (quotient id 128)))))))) | |
187 | + | (cons first-byte rest))))) | |
188 | + | (_ (throw 'invalid-identifier)))) | |
189 | + | (lambda _ (throw 'primitive-type)))) | |
73 | 190 | ||
74 | 191 | ;; Note that a sequence depends on the types of its contents | |
75 | 192 | (define* (asn1:sequence . types) | |
76 | 193 | (make-asn1-type | |
77 | - | "sequence" #x30 | |
194 | + | "sequence" #x10 #f #t | |
78 | 195 | (lambda (bv pos len) | |
79 | 196 | (let loop ((result '()) (types types) (rest-len len) (pos pos)) | |
80 | 197 | (match types | |
… | |||
91 | 208 | (throw 'incompatible-type-and-value-sizes)) | |
92 | 209 | (apply | |
93 | 210 | bv-append | |
94 | - | (map encode-asn1 types value))))) | |
211 | + | (map encode-asn1 types value))) | |
212 | + | (lambda (value) value))) | |
95 | 213 | ||
96 | 214 | ||
97 | 215 | ;; Now these functions are related to parsing or producing DER-encoded values | |
… | |||
118 | 236 | (- first-byte 127); one for the size byte too, so 127 not 128 | |
119 | 237 | 1))) | |
120 | 238 | ||
239 | + | (define (constructed? type-byte) | |
240 | + | (not (eq? (logand type-byte #x20) 0))) | |
241 | + | ||
242 | + | (define (decode-asn1-array bv pos type) | |
243 | + | (let loop ((value '()) (pos pos)) | |
244 | + | (if (= (bytevector-u8-ref bv pos) 0) | |
245 | + | (begin | |
246 | + | (unless (= (bytevector-u8-ref bv (+ pos 1)) 0) | |
247 | + | (throw 'invalid-EOC-length)) | |
248 | + | (cons ((asn1-type-aggregator type) (reverse value)) (+ pos 2))) | |
249 | + | (let* ((res (decode-asn1-aux bv pos type)) | |
250 | + | (val (car res)) | |
251 | + | (pos (cdr res))) | |
252 | + | (loop (cons val value) pos))))) | |
253 | + | ||
121 | 254 | (let* ((type-byte (bytevector-u8-ref bv pos)) | |
255 | + | (constructed? (constructed? type-byte)) | |
122 | 256 | (pos (+ pos 1)) | |
257 | + | (len-byte (bytevector-u8-ref bv pos)) | |
123 | 258 | (len (decode-len bv pos)) | |
124 | 259 | (pos (+ pos (lenlen bv pos)))) | |
125 | - | (unless (equal? type-byte (asn1-type-type type)) | |
126 | - | (throw 'invalid-type-byte)) | |
127 | - | (cons ((asn1-type-parser type) bv pos len) (+ pos len)))) | |
260 | + | (unless (equal? (- type-byte (if constructed? #x20 0)) (asn1-type-type type)) | |
261 | + | (throw 'invalid-type-byte type-byte type)) | |
262 | + | (when (and constructed? (not (asn1-type-constructed? type))) | |
263 | + | (throw 'invalid-constructed-type)) | |
264 | + | (when (and (not constructed?) (not (asn1-type-primitive? type))) | |
265 | + | (throw 'invalid-primitive-type)) | |
266 | + | (if (and constructed? (equal? len-byte #x80)) | |
267 | + | (decode-asn1-array bv pos type) | |
268 | + | (cons ((asn1-type-parser type) bv pos len) (+ pos len))))) | |
128 | 269 | ||
129 | 270 | (define (decode-asn1 bv type) | |
130 | 271 | "Decode the content of @var{bv}, a DER record of @var{type}" | |
… | |||
135 | 276 | "Encode the @var{value} of @var{type} into a DER record represented by a | |
136 | 277 | bytevector." | |
137 | 278 | (let* ((type-byte (asn1-type-type type)) | |
279 | + | (type-byte (if (not (asn1-type-primitive? type)) | |
280 | + | (+ #x20 type-byte) | |
281 | + | type-byte)) | |
138 | 282 | (value ((asn1-type-producer type) value)) | |
139 | 283 | (len (encode-len (bytevector-length value))) | |
140 | 284 | (type-bv (make-bytevector 1))) | |
141 | 285 | (bytevector-u8-set! type-bv 0 type-byte) | |
142 | - | (pk 'encode type-bv len value) | |
143 | 286 | (bv-append type-bv len value))) | |
144 | 287 | ||
145 | 288 | (define (bv-append . bvs) |