summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--guix/pk-crypto.scm83
-rw-r--r--tests/pk-crypto.scm42
2 files changed, 124 insertions, 1 deletions
diff --git a/guix/pk-crypto.scm b/guix/pk-crypto.scm
index 9d093b34b0e..d8fbb6f85b4 100644
--- a/guix/pk-crypto.scm
+++ b/guix/pk-crypto.scm
@@ -18,7 +18,9 @@
18 18
19(define-module (guix pk-crypto) 19(define-module (guix pk-crypto)
20 #:use-module (guix config) 20 #:use-module (guix config)
21 #:use-module ((guix utils) #:select (bytevector->base16-string)) 21 #:use-module ((guix utils)
22 #:select (bytevector->base16-string
23 base16-string->bytevector))
22 #:use-module (system foreign) 24 #:use-module (system foreign)
23 #:use-module (rnrs bytevectors) 25 #:use-module (rnrs bytevectors)
24 #:use-module (ice-9 match) 26 #:use-module (ice-9 match)
@@ -26,7 +28,12 @@
26 string->gcry-sexp 28 string->gcry-sexp
27 gcry-sexp->string 29 gcry-sexp->string
28 number->gcry-sexp 30 number->gcry-sexp
31 gcry-sexp-car
32 gcry-sexp-cdr
33 gcry-sexp-nth
34 gcry-sexp-nth-data
29 bytevector->hash-data 35 bytevector->hash-data
36 hash-data->bytevector
30 sign 37 sign
31 verify 38 verify
32 generate-key 39 generate-key
@@ -105,6 +112,61 @@
105 (loop (* len 2)) 112 (loop (* len 2))
106 (pointer->string buf size "ISO-8859-1"))))))) 113 (pointer->string buf size "ISO-8859-1")))))))
107 114
115(define gcry-sexp-car
116 (let* ((ptr (libgcrypt-func "gcry_sexp_car"))
117 (proc (pointer->procedure '* ptr '(*))))
118 (lambda (lst)
119 "Return the first element of LST, an sexp, if that element is a list;
120return #f if LST or its first element is not a list (this is different from
121the usual Lisp 'car'.)"
122 (let ((result (proc (gcry-sexp->pointer lst))))
123 (if (null-pointer? result)
124 #f
125 (pointer->gcry-sexp result))))))
126
127(define gcry-sexp-cdr
128 (let* ((ptr (libgcrypt-func "gcry_sexp_cdr"))
129 (proc (pointer->procedure '* ptr '(*))))
130 (lambda (lst)
131 "Return the tail of LST, an sexp, or #f if LST is not a list."
132 (let ((result (proc (gcry-sexp->pointer lst))))
133 (if (null-pointer? result)
134 #f
135 (pointer->gcry-sexp result))))))
136
137(define gcry-sexp-nth
138 (let* ((ptr (libgcrypt-func "gcry_sexp_nth"))
139 (proc (pointer->procedure '* ptr `(* ,int))))
140 (lambda (lst index)
141 "Return the INDEXth nested element of LST, an s-expression. Return #f
142if that element does not exist, or if it's an atom. (Note: this is obviously
143different from Scheme's 'list-ref'.)"
144 (let ((result (proc (gcry-sexp->pointer lst) index)))
145 (if (null-pointer? result)
146 #f
147 (pointer->gcry-sexp result))))))
148
149(define (dereference-size_t p)
150 "Return the size_t value pointed to by P."
151 (bytevector-uint-ref (pointer->bytevector p (sizeof size_t))
152 0 (native-endianness)
153 (sizeof size_t)))
154
155(define gcry-sexp-nth-data
156 (let* ((ptr (libgcrypt-func "gcry_sexp_nth_data"))
157 (proc (pointer->procedure '* ptr `(* ,int *))))
158 (lambda (lst index)
159 "Return as a string the INDEXth data element (atom) of LST, an
160s-expression. Return #f if that element does not exist, or if it's a list.
161Note that the result is a Scheme string, but depending on LST, it may need to
162be interpreted in the sense of a C string---i.e., as a series of octets."
163 (let* ((size* (bytevector->pointer (make-bytevector (sizeof '*))))
164 (result (proc (gcry-sexp->pointer lst) index size*)))
165 (if (null-pointer? result)
166 #f
167 (pointer->string result (dereference-size_t size*)
168 "ISO-8859-1"))))))
169
108(define (number->gcry-sexp number) 170(define (number->gcry-sexp number)
109 "Return an s-expression representing NUMBER." 171 "Return an s-expression representing NUMBER."
110 (string->gcry-sexp (string-append "#" (number->string number 16) "#"))) 172 (string->gcry-sexp (string-append "#" (number->string number 16) "#")))
@@ -117,6 +179,25 @@ for use as the data for 'sign'."
117 hash-algo 179 hash-algo
118 (bytevector->base16-string bv)))) 180 (bytevector->base16-string bv))))
119 181
182(define (latin1-string->bytevector str)
183 "Return a bytevector representing STR."
184 ;; XXX: In Guile 2.0.9 and later, we would use 'string->bytevector' for
185 ;; that.
186 (let ((bytes (map char->integer (string->list str))))
187 (u8-list->bytevector bytes)))
188
189(define (hash-data->bytevector data)
190 "Return two values: the hash algorithm (a string) and the hash value (a
191bytevector) extract from DATA, an sexp as returned by 'bytevector->hash-data'.
192Return #f if DATA does not conform."
193 (let ((hash (find-sexp-token data 'hash)))
194 (if hash
195 (let ((algo (gcry-sexp-nth-data hash 1))
196 (value (gcry-sexp-nth-data hash 2)))
197 (values (latin1-string->bytevector value)
198 algo))
199 (values #f #f))))
200
120(define sign 201(define sign
121 (let* ((ptr (libgcrypt-func "gcry_pk_sign")) 202 (let* ((ptr (libgcrypt-func "gcry_pk_sign"))
122 (proc (pointer->procedure int ptr '(* * *)))) 203 (proc (pointer->procedure int ptr '(* * *))))
diff --git a/tests/pk-crypto.scm b/tests/pk-crypto.scm
index 1acce13f0a2..7c54e729ad5 100644
--- a/tests/pk-crypto.scm
+++ b/tests/pk-crypto.scm
@@ -21,6 +21,8 @@
21 #:use-module (guix utils) 21 #:use-module (guix utils)
22 #:use-module (guix hash) 22 #:use-module (guix hash)
23 #:use-module (srfi srfi-1) 23 #:use-module (srfi srfi-1)
24 #:use-module (srfi srfi-11)
25 #:use-module (srfi srfi-26)
24 #:use-module (srfi srfi-64) 26 #:use-module (srfi srfi-64)
25 #:use-module (rnrs bytevectors) 27 #:use-module (rnrs bytevectors)
26 #:use-module (rnrs io ports) 28 #:use-module (rnrs io ports)
@@ -75,6 +77,38 @@
75 77
76(gc) 78(gc)
77 79
80(test-equal "gcry-sexp-car + cdr"
81 '("(b \n (c xyz)\n )")
82 (let ((lst (string->gcry-sexp "(a (b (c xyz)))")))
83 (map (lambda (sexp)
84 (and sexp (string-trim-both (gcry-sexp->string sexp))))
85 ;; Note: 'car' returns #f when the first element is an atom.
86 (list (gcry-sexp-car (gcry-sexp-cdr lst))))))
87
88(gc)
89
90(test-equal "gcry-sexp-nth"
91 '(#f "(b pqr)" "(c \"456\")" "(d xyz)" #f #f)
92 (let ((lst (string->gcry-sexp "(a (b 3:pqr) (c 3:456) (d 3:xyz))")))
93 (map (lambda (sexp)
94 (and sexp (string-trim-both (gcry-sexp->string sexp))))
95 (unfold (cut > <> 5)
96 (cut gcry-sexp-nth lst <>)
97 1+
98 0))))
99
100(gc)
101
102(test-equal "gcry-sexp-nth-data"
103 '("Name" "Otto" "Meier" #f #f #f)
104 (let ((lst (string->gcry-sexp "(Name Otto Meier (address Burgplatz))")))
105 (unfold (cut > <> 5)
106 (cut gcry-sexp-nth-data lst <>)
107 1+
108 0)))
109
110(gc)
111
78;; XXX: The test below is typically too long as it needs to gather enough entropy. 112;; XXX: The test below is typically too long as it needs to gather enough entropy.
79 113
80;; (test-assert "generate-key" 114;; (test-assert "generate-key"
@@ -85,6 +119,14 @@
85;; (find-sexp-token key 'public-key) 119;; (find-sexp-token key 'public-key)
86;; (find-sexp-token key 'private-key)))) 120;; (find-sexp-token key 'private-key))))
87 121
122(test-assert "bytevector->hash-data->bytevector"
123 (let* ((bv (sha256 (string->utf8 "Hello, world.")))
124 (data (bytevector->hash-data bv "sha256")))
125 (and (gcry-sexp? data)
126 (let-values (((value algo) (hash-data->bytevector data)))
127 (and (string=? algo "sha256")
128 (bytevector=? value bv))))))
129
88(test-assert "sign + verify" 130(test-assert "sign + verify"
89 (let* ((pair (string->gcry-sexp %key-pair)) 131 (let* ((pair (string->gcry-sexp %key-pair))
90 (secret (find-sexp-token pair 'private-key)) 132 (secret (find-sexp-token pair 'private-key))