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) | |