aboutsummaryrefslogtreecommitdiff
path: root/openssl/agent/pkcs11/url.hxx
blob: b8ca056480acaf78d9f9b031bb073b5b27c81c31 (plain)
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// file      : openssl/agent/pkcs11/url.hxx -*- C++ -*-
// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef OPENSSL_AGENT_PKCS11_URL_HXX
#define OPENSSL_AGENT_PKCS11_URL_HXX

#include <libbutl/url.mxx>

#include <openssl/types.hxx>
#include <openssl/utility.hxx>

// glibc defines these macros in its <sys/types.h>.
//
#ifdef major
#  undef major
#endif

#ifdef minor
#  undef minor
#endif

namespace openssl
{
  namespace agent
  {
    namespace pkcs11
    {
      // RFC7512 The PKCS #11 URI Scheme.
      //
      // Traits class for the PKCS#11 URL object.
      //
      // Notes:
      //
      // - The 'pkcs11:' URI scheme is rootless and doesn't use the fragment
      //   component.
      //
      // - The one-level path component is a sequence of semicolon-separated
      //   attribute name/value pairs that identify the referenced entity. It
      //   is stored in the URL-encoded representation as the id attribute
      //   contains binary data.
      //
      // - The query is a sequence of ampersand-separated access attribute
      //   name/value pairs that may or may not be used by the URL consumer.
      //
      // - All attribute values are textual, except for the id attribute which
      //   is binary.
      //
      // - There shouldn't be duplicate attributes in the path and query
      //   components.
      //
      // - Both path and query components can contain vendor-specific
      //   attributes.
      //
      // - An unrecognized attribute in the path component results in the
      //   parsing error. An unrecognized attribute in the query component is
      //   skipped.
      //
      // - The URL-referenced entity kind is context-specific. For example,
      //   the pkcs11:token=abc URL can refer the abc token or all objects
      //   stored in the abc token.
      //
      // - An attribute that is not present in the URL path component matches
      //   everything. Each additional attribute present in the path component
      //   further restricts the selection. Thus, in particular, the 'pkcs11:'
      //   URL is valid and matches everything.
      //
      struct url_traits
      {
        using string_type = string;
        using path_type   = string;

        using scheme_type    = string;
        using authority_type = butl::basic_url_authority<string_type>;

        static optional<scheme_type>
        translate_scheme (const string_type&,
                          string_type&&,
                          optional<authority_type>&,
                          optional<path_type>&,
                          optional<string_type>&,
                          optional<string_type>&,
                          bool&);

        static string_type
        translate_scheme (string_type&,
                          const scheme_type&,
                          const optional<authority_type>&,
                          const optional<path_type>&,
                          const optional<string_type>&,
                          const optional<string_type>&,
                          bool);

        static path_type
        translate_path (string_type&&);

        static string_type
        translate_path (const path_type&);
      };

      using url = butl::basic_url<string, url_traits>;

      // PKCS#11 entity (storage object, token, slot, or module) identity
      // attributes.
      //
      struct library_version
      {
        unsigned char major;
        unsigned char minor;

        // Create the version object from its string representation. Throw
        // invalid_argument on the parsing error.
        //
        explicit
        library_version (const string&);

        library_version (unsigned char mj, unsigned char mn)
            : major (mj), minor (mn) {}
      };

      class identity
      {
      public:
        // Module.
        //
        using library_version_type = pkcs11::library_version;

        optional<string>               library_manufacturer;
        optional<library_version_type> library_version;
        optional<string>               library_description;

        // Slot.
        //
        // Note that not all PKCS#11 libraries guarantee slot id to be stable
        // across initializations.
        //
        optional<unsigned long> slot_id;
        optional<string>        slot_manufacturer;
        optional<string>        slot_description;

        // Token.
        //
        optional<string> serial;
        optional<string> token;        // Token label.
        optional<string> model;
        optional<string> manufacturer;

        // Storage object.
        //
        optional<vector<unsigned char>> id;

        optional<string> object; // Object label.
        optional<string> type;   // cert, data, private, public, or
                                 // secret-key.

        // Parse the path component of pkcs11_url object. Throw
        // invalid_argument if invalid attribute is encountered.
        //
        explicit
        identity (const url&);

        // Create an identity that matches all PKCS#11 entities in the system.
        //
        identity () = default;
      };

      // PKCS#11 entity access attributes.
      //
      class access
      {
      public:
        optional<string> pin_value;
        optional<string> pin_source;

        // The library name with an extension and "lib" prefix stripped.
        //
        optional<path> module_name;

        // The library absolute path or the directory path where the PKCS#11
        // libraries are located.
        //
        optional<path> module_path;

        // Parse the query component of pkcs11_url object. Throw
        // invalid_argument if invalid attribute is encountered.
        //
        explicit
        access (const url&);

        // Create an object that provides no access attributes.
        //
        access () = default;
      };

      inline bool
      operator== (const library_version& x, const library_version& y)
      {
        return x.major == y.major && x.minor == y.minor;
      }

      inline bool
      operator!= (const library_version& x, const library_version& y)
      {
        return !(x == y);
      }

      inline bool
      operator== (const identity& x, const identity& y)
      {
        return
          // Module.
          //
          x.library_manufacturer == y.library_manufacturer &&
          x.library_version      == y.library_version      &&
          x.library_description  == y.library_description  &&

          // Slot.
          //
          x.slot_id              == y.slot_id              &&
          x.slot_manufacturer    == y.slot_manufacturer    &&
          x.slot_description     == y.slot_description     &&

          // Token.
          //
          x.serial               == y.serial               &&
          x.token                == y.token                &&
          x.model                == y.model                &&
          x.manufacturer         == y.manufacturer         &&

          // Storage object.
          //
          x.id                   == y.id                   &&
          x.object               == y.object               &&
          x.type                 == y.type;
      }

      inline bool
      operator!= (const identity& x, const identity& y)
      {
        return !(x == y);
      }
    }
  }
}

#endif // OPENSSL_AGENT_PKCS11_URL_HXX