aboutsummaryrefslogtreecommitdiff
path: root/openssl/README
blob: 9c8a859d877aac30e02a06d2ce3277d9ac587c93 (plain) (blame)
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
$Id$

OpenSSL hacked to add support for the RFC 3779 X.509 v3 extensions.



Some notes on OpenSSL internals.

O'Reilly "Network Security with OpenSSL" is a bit dated (four years
old, corresponds roughly to OpenSSL 0.9.7), but still appears to be
the closest thing there is to coherent documentation.  Some updates
and machine readable copies of examples are available at
http://www.opensslbook.com/.  In spite of its age, the book is useful
as it gives a readable overview of bit and pieces of OpenSSL's
internal programming environment which one would otherwise have to
absorb from the code via osmosis.  Chapter 10 is particularly useful,
as are the sections on error handling and abstract I/O (the ERR and
BIO packages, respectively) in chapter 4.

OpenSSL's own doc is very patchy, although fairly extensive in places.
Most of it eventually comes down to "Use the Source, Luke" with
pointers on which bit of source serves as an interesting example.

For x509v3 extentions, the place to start is doc/openssl.txt,
which, oddly, turns out to be mostly about certificate extensions.  It
gives an overview of the mechanisms, in particular of the method
routine interface for certificate extensions.  For something like the
RFC 3779 extensions, it's pretty clear that we need to use a "raw"
extension (which, as far as I can tell, just means that the RFC 3779
stuff is complicated enough that the extension handler has to do a lot
of work to deal with a complex ASN.1 structure that the rest of the
code doesn't know much about).

openssl.txt refers the reader to the certificate policy extension
handler as an example of how to write a raw extension. The relevant
file appears to be crypto/x509v3/v3_cpols.c.  This is indeed a
complicated mess, but it's a surprisingly good tutorial, on about the
tenth reading.

Aside from the method interface and routines described in openssl.txt,
v3_cpols.c also includes a bunch of template junk for the ASN.1
encoder and decoder.  According to README.ASN1 (q.v.), the ASN.1 code
is in transition.  I haven't attempted to understand the "old" ASN.1
code; the new stuff is template driven.  README.ASN.1 mumbles about
this a bit, but the real doc on the template stuff appears to be the
definitions in crypto/asn1/asn1t.h.  Given that and a reading
knowledge of ASN.1, the template definitions in v3_cpols.c are fairly
obviously a direct hand translation from ASN.1 into C.

General note on global symbols in OpenSSL: always look at the header
file for any global symbol you're using.  In fact, it's probably best
to do a global search (m-x tags-search if you're an emacs user) for
all instances of a global symbol before attempting to use it, as there
are a lot of things that one just has to know about how all the global
stuff hangs together.  There are header files full of magic
definitions that one just has to one need to be extended.  There are
magic pre-sorted lists of handlers that one just needs to know about.
Little or none of this is documented.  Use the Source, Luke.

Oh, and the indentation style is demented.

Header files you definitely need to read if you're going to touch this
stuff:

    crypto/x509v3/x509v3.h
    crypto/x509v3/ext_dat.h
    crypto/stack/safestack.h
    crypto/asn1/asn1t.h
    crypto/asn1/asn1.h
    crypto/objects/objects.h

Automatically generated header files you'll need to skim, then go read
the input files listed in the header comments and perhaps the
generating Perl code:

    crypto/objects/obj_mac.h
    crypto/objects/obj_dat.h

Much of the code shows a heavy Perl influence, presumably dating back
clear to Eric Young.  Some of the internal data structure operators
have names that only make sense to a Perl programmer.  Where code is
automatically generated, it's done by Perl scripts.  The configuration
language for the whole package is a Perl script.  Assembly code is all
wrapped up inside perl scripts in a moderately clever attempt at being
able to write the assembly language only once and use it with various
assemblers with nontrivially different syntax.  Much of the
documentation markup (including manual pages) for the C code is .pod.

At this point I think I understand enough that I could write the RFC
3779 extension I/O routines, although no doubt some of it would be
take a while since I would be learning my way through some of the
library routines as I go.

I have not yet written up a syntax description for how we would encode
the RFC 3779 extensions in an openssl.conf file.  That should be
fairly straightforward, if a bit tedious.

I have not yet figured out where to hook in the extra goop that RFC
3779 will need for verification.  Making extensions critical is easy
enough, but the validation stuff in RFC 3779 2.3 and 3.3 needs to go
somewhere, I'm not quite sure where yet.  To the extent that I
understand how OpenSSL does such things (not very well, yet), the
"-purpose" flags to the CLI's x509 and verify commands (q.v.) look
like the right hooks.  I haven't (yet) investigated the code in back
of the "-purpose" mechanism.

At the moment the consensus appears to be that we should be using
OpenSSL 0.9.8b, in order to get SHA-256 support.  My research to date
has been on OpenSSL 0.9.8a, but I doubt that any of the stuff I've
been looking at has changed enough to matter.



Possible encoding for RFC 3779 extensions in openssl.conf format.
General plan:

  SEQUENCE OF maps to a list of items; for (code) simplicity each list
  will probably be a separate named section, although I suppose we
  could try to handle comma-separated lists to make it easier for
  people with really simple configurations.

  SEQUENCEs map to mandatory fields on a single command line.

  Optional fields (including CHOICEs with a NULL branch) map to
  optional fields on a single config line.  Syntax is likely to be
  somewhat arbitrary, with preference given to simplifying common
  cases (ie, if you really need to specify a non-null SAFI, you'll
  have to use the long form).

  Where possible, a SEQUENCE containing objects which themselves
  contain optional items will be collapsed so that the whole mess can
  be a config file line.

ASN.1 from RFC 3779 2.2.3:

   IPAddressFamily     ::= SEQUENCE {    -- AFI & optional SAFI --
      addressFamily        OCTET STRING (SIZE (2..3)),
      ipAddressChoice      IPAddressChoice }

   IPAddressChoice     ::= CHOICE {
      inherit              NULL, -- inherit from issuer --
      addressesOrRanges    SEQUENCE OF IPAddressOrRange }

These can be encoded as a single line, of either two or three fields:

  Two fields:	AFI, name-of-address-block

  Three fields:	AFI, SAFI, name-of-address-block

Would help if we had a magic character that can't possibly be a legal
name for an adddress block which we can use to denote inheritance.
Need to work out -some- way to denote inheritance.

   IPAddressOrRange    ::= CHOICE {
      addressPrefix        IPAddress,
      addressRange         IPAddressRange }

   IPAddressRange      ::= SEQUENCE {
      min                  IPAddress,
      max                  IPAddress }

   IPAddress           ::= BIT STRING

These can be handled as a single line: if there are two prefixes, it's
an addressRange, otherwise it's an addressPrefix.

ASN.1 from RFC 3779 3.2.3:

   ASIdentifiers       ::= SEQUENCE {
       asnum               [0] EXPLICIT ASIdentifierChoice OPTIONAL,
       rdi                 [1] EXPLICIT ASIdentifierChoice OPTIONAL}

   ASIdentifierChoice  ::= CHOICE {
      inherit              NULL, -- inherit from issuer --
      asIdsOrRanges        SEQUENCE OF ASIdOrRange }

Since this is two optional fields, it'd probably be easiest to make
these independent variables in the config file, one for asnum, one for
rdi.  They'd have the same syntax, which would be a single line
consisting either of the name of a section to use (asIdsOrRanges) or a
magic character denoting inheritance.

This seems a little wasteful, since it'd be nice to be able to do the
AS numbers inline.


   ASIdOrRange         ::= CHOICE {
       id                  ASId,
       range               ASRange }

   ASRange             ::= SEQUENCE {
       min                 ASId,
       max                 ASId }

   ASId                ::= INTEGER

These can be handled as a single line: if there are two numbers, it's
a range, otherwise it's an id.  Since it'd be nice to be able to do
these without requiring a separate section, perhaps two numbers
separated by a hyphen are a range, so we can retain comma for lists
(and use the @section notation for indirect sections).