-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathTODO
214 lines (162 loc) · 8.98 KB
/
TODO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
hey emacs, show me an -*- mode: outline -*-
* misc
** cleanup octet-stream: positions are either INDEX or POSITION, not both
The latter requires :SHADOW adjustments in Ironclad's DEFPACKAGE.
** WRITE-SEQUENCE on crypting-streams
** HMACING-STREAM
* ciphers to add
CAST6
SEED
MARS
Serpent
Camellia
...others?...
* add OpenPGP functions
This would involve writing some simple base64 encoding and decoding.
I'm not sure how to add this and achieve the right amount of generality
and functionality. Just writing an OpenPGP parser is straightforward,
but determining what to do with the data is a little more complicated.
* add {EN,DE}CRYPTING-STREAM capabilities
Encrypts data written to it before writing the (now-encrypted) data to
an underlying stream. Of course, the equivalent functionality is
available for decrypting. This might finesse the current lack of
padding functionality in the library: when the stream is closed, the
appropriate amount and kind of padding is added. Not sure that this is
necessarily the right idea, although when people are encrypting data,
they are generally doing so before writing said data someplace else. I
don't encrypt data in memory just for the fun of it.
(These are partially written, see octet-stream.lisp.)
* make a condition hierarchy for the library
Some conditions have been added as of 0.7, but there probably need to be
more, with helpful messages along the way.
* move generic function definitions to their own file
There's a lot of generic function definitions floating around as of
version 0.5 and there are likely to be many more as the library grows.
Perhaps the DEFGENERIC forms should be moved into their own file;
such a change would make the source tree cleaner and provide a good
starting point for people interested in examining the library's
functionality.
* add functional version of encryption and decryption
{ENCRYPT,DECRYPT}-MESSAGE would be perfect for this; although they were
originally conceived for public-key operations (and therefore they have
to return a fresh octet vector), they make perfect candidates for
providing functional interfaces to encryption and decryption as well.
Figuring out short block interfaces for this and padding issues,
however, will be a little tricky.
* remove generic function calls from inner loops
ENCRYPT-WITH-MODE, by virtue of calling <CIPHER>-ENCRYPT-BLOCK on
every iteration of the loop, requires <CIPHER>-ENCRYPT-BLOCK to
repeatedly extract the cipher-specific data from the provided cipher
context. No idea if this is a bottleneck (probably not).
Doing this extraction on every iteration of the loop is overhead,
though--unnecessary overhead compared to a C implementation. Pulling
the extraction out of the loop in a clean, cipher-independent manner is
probably pretty hairy, however.
* figure out interface for extra cipher creation parameters
RC5, for instance, is configurable in the number of rounds. The number
of rounds must be fixed the way the current system works. Configuring
the number of rounds for TEA and XTEA would be another example of where
this is useful. Surely there are other reasons, too.
* add more cipher modes of operation
CBC with ciphertext stealing (CBC-CTS) (this would require some sort
of ENCRYPT-FINAL-BLOCK interface so we would know when to perform the
ciphertext stealing)
PCBC, for all those Lispers who want to implement Kerberos 4
OpenPGP CFB
* add padding primitives
This should be combined, somehow, with an ENCRYPT-FINAL-BLOCK generic
function. This lets the caller do padding and encryption in one shot.
An alternative to ENCRYPT-FINAL-BLOCK is to provide a
:PROCESS-FINAL-BLOCK argument to {ENCRYPT,DECRYPT}, which seems cleaner
and easier to add.
* efficient 32-bit implementations of SHA2-{512,384}
These digests are currently implemented with straight 64-bit arithmetic,
which is elegant, but causes a lot of consing on 32-bit platforms. Is
it worth spending the time to tweak these?
* add other MACs
The NESSIE project has a boatload of MAC recommendations with test
vectors and everything. Adding other MACs would help with cleaning up
the MAC interface (or lack thereof).
** unified interface for MAC construction, updating, etc.
* add other digests
Are there any other reputable hash functions?
* figure out interface for stream ciphers
WiderWake 4+1
SEAL (intellectual property issues, although that doesn't seem to stop
many other crypto libraries)
* add public-key crypto
DSA signing and verification routines have been added as of version
0.11. RSA, Elgamal, elliptic-curve crypto, and others remain to be
added. One issue that has yet to be resolved is how to handle the
myriad signature/encryption schemes for RSA.
* random number generation
Doing this right would require adding an interface to get at entropy
sources on various operating systems. We could just punt this out to
the user and have an ADD-ENTROPY function that the user would need to
call from time to time. Very inconvenient, though.
* blue-sky ideas
** implementation-specific algorithm implementations
Ironclad is written with implementations that are capable of performing
32-bit unboxed arithmetic in mind. However, there is no reason to leave
other implementations out in the cold. I particularly have in mind
ABCL, whose clean Java integration could facilitate using Java's crypto
routines for many of the algorithms Ironclad provides.
Using 32-bit integer arithmetic in LispWorks (SYSTEM:INT32-*) and
DEF*LAPFUNCTION in ClozureCL, along with architecture-specific VOPs
and/or DEF{KNOWN,OPTIMIZER,TRANSFORM} in SBCL/CMUCL are other ways of
doing this.
** compilable encryption and decryption routines
One trick that's commonly used in high-performance crypto libraries is
unrolling inner loops of ciphers, which are generally Feistel networks
of some sort. This transformation has many benefits: avoiding jumps and
compiling more efficient code for structure accesses, to name two.
Ironclad features unrolled loops in various places (e.g. the CAST5 and
Blowfish ciphers). Unrolled loops can be particularly helpful in Common
Lisp because the compiler can often optimize away things like array
bounds checks.
Unfortunately, this tends to limit the libraries to only handling a
fixed number of rounds (or other configurable parameters of block
ciphers). Accomodating variable numbers of rounds makes life easier for
the truly paranoid and is more in the spirit of the ciphers as
originally designed.
One way of getting around this limitation would be to use Common Lisp's
provision of the COMPILE function at create-the-cipher time. One could
compile--on demand--specialized encryption/decryption routines that only
accomodated a fixed number of rounds (or other static configuration
parameters). This facility would be particularly helpful for those
ciphers whose round keys are variable in the number of rounds chosen;
bounds checking for accesses to these keys could be done away with
entirely (except perhaps for a check to ensure the round key vector is
of the proper length and type). Furthermore, the round keys could
actually be compiled directly into the code--as 32-bit constant
arguments on the x86, for example. Such a change would necessarily make
the compiled routines key-specific, but perhaps that would be OK.
(When reading the specifications for Blowfish and Twofish, the authors
make much of this capability by citing screaming performance numbers for
this scenario while noting that modifying the code for each individual
key is difficult. In Ironclad, providing three differing levels of
generality--general, n-rounds-specific, and key-specific--would be
relatively easy compared to the difficulty of doing it in C.)
Changes to MAKE-CIPHER--a keyword argument specifying the level of
specialization--would be necessary. Extensive changes to the individual
block ciphers would also be necessary. Perhaps this sort of facility
need not be added to all ciphers; the common ones could come first
(e.g. AES) and less-common ones would be converted as people contributed
patches or needs were found for them.
** use word-aligned loads when possible
The current code uses byte loads + shifts and ors to fetch
(UNSIGNED-BYTE 32) values out of a (SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*)).
Some implementations (I have in mind particularly SBCL and CMUCL) could
use a more efficient mechanism if the offset of the (UNSIGNED-BYTE 32)
value was known to be four-byte aligned. Once this was done for each
encryption/decryption function for a particular block cipher, the
high-level generic functions could call efficient versions if possible,
eliminating some overhead.
There is actually some (SBCL) support for this in cipher.lisp, in the
alternate definition for WITH-WORDS. It doesn't make that much of a
difference--at least not in the case where WITH-WORDS needs to check for
alignment and safety. It might be a win if there were several
different *-ENCRYPT-BLOCK functions and the high-level ones knew which
one to call, but...
* add option to allow INTEGER-TO-OCTETS to output directly to a buffer
This could be handy in certain internals, e.g. in GENERATE-BLOCKS.