xref: /freebsd-src/crypto/openssl/doc/man7/proxy-certificates.pod (revision 17f01e9963948a18f55eb97173123702c5dae671)
1*17f01e99SJung-uk Kim=pod
2*17f01e99SJung-uk Kim
3*17f01e99SJung-uk Kim=encoding UTF-8
4*17f01e99SJung-uk Kim
5*17f01e99SJung-uk Kim=head1 NAME
6*17f01e99SJung-uk Kim
7*17f01e99SJung-uk Kimproxy-certificates - Proxy certificates in OpenSSL
8*17f01e99SJung-uk Kim
9*17f01e99SJung-uk Kim=head1 DESCRIPTION
10*17f01e99SJung-uk Kim
11*17f01e99SJung-uk KimProxy certificates are defined in RFC 3820.  They are used to
12*17f01e99SJung-uk Kimextend rights to some other entity (a computer process, typically, or
13*17f01e99SJung-uk Kimsometimes to the user itself).  This allows the entity to perform
14*17f01e99SJung-uk Kimoperations on behalf of the owner of the EE (End Entity) certificate.
15*17f01e99SJung-uk Kim
16*17f01e99SJung-uk KimThe requirements for a valid proxy certificate are:
17*17f01e99SJung-uk Kim
18*17f01e99SJung-uk Kim=over 4
19*17f01e99SJung-uk Kim
20*17f01e99SJung-uk Kim=item *
21*17f01e99SJung-uk Kim
22*17f01e99SJung-uk KimThey are issued by an End Entity, either a normal EE certificate, or
23*17f01e99SJung-uk Kimanother proxy certificate.
24*17f01e99SJung-uk Kim
25*17f01e99SJung-uk Kim=item *
26*17f01e99SJung-uk Kim
27*17f01e99SJung-uk KimThey must not have the B<subjectAltName> or B<issuerAltName>
28*17f01e99SJung-uk Kimextensions.
29*17f01e99SJung-uk Kim
30*17f01e99SJung-uk Kim=item *
31*17f01e99SJung-uk Kim
32*17f01e99SJung-uk KimThey must have the B<proxyCertInfo> extension.
33*17f01e99SJung-uk Kim
34*17f01e99SJung-uk Kim=item *
35*17f01e99SJung-uk Kim
36*17f01e99SJung-uk KimThey must have the subject of their issuer, with one B<commonName>
37*17f01e99SJung-uk Kimadded.
38*17f01e99SJung-uk Kim
39*17f01e99SJung-uk Kim=back
40*17f01e99SJung-uk Kim
41*17f01e99SJung-uk Kim=head2 Enabling proxy certificate verification
42*17f01e99SJung-uk Kim
43*17f01e99SJung-uk KimOpenSSL expects applications that want to use proxy certificates to be
44*17f01e99SJung-uk Kimspecially aware of them, and make that explicit.  This is done by
45*17f01e99SJung-uk Kimsetting an X509 verification flag:
46*17f01e99SJung-uk Kim
47*17f01e99SJung-uk Kim    X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
48*17f01e99SJung-uk Kim
49*17f01e99SJung-uk Kimor
50*17f01e99SJung-uk Kim
51*17f01e99SJung-uk Kim    X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_ALLOW_PROXY_CERTS);
52*17f01e99SJung-uk Kim
53*17f01e99SJung-uk KimSee L</NOTES> for a discussion on this requirement.
54*17f01e99SJung-uk Kim
55*17f01e99SJung-uk Kim=head2 Creating proxy certificates
56*17f01e99SJung-uk Kim
57*17f01e99SJung-uk KimCreating proxy certificates can be done using the L<openssl-x509(1)>
58*17f01e99SJung-uk Kimcommand, with some extra extensions:
59*17f01e99SJung-uk Kim
60*17f01e99SJung-uk Kim    [ v3_proxy ]
61*17f01e99SJung-uk Kim    # A proxy certificate MUST NEVER be a CA certificate.
62*17f01e99SJung-uk Kim    basicConstraints=CA:FALSE
63*17f01e99SJung-uk Kim
64*17f01e99SJung-uk Kim    # Usual authority key ID
65*17f01e99SJung-uk Kim    authorityKeyIdentifier=keyid,issuer:always
66*17f01e99SJung-uk Kim
67*17f01e99SJung-uk Kim    # The extension which marks this certificate as a proxy
68*17f01e99SJung-uk Kim    proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:1,policy:text:AB
69*17f01e99SJung-uk Kim
70*17f01e99SJung-uk KimIt's also possible to specify the proxy extension in a separate section:
71*17f01e99SJung-uk Kim
72*17f01e99SJung-uk Kim    proxyCertInfo=critical,@proxy_ext
73*17f01e99SJung-uk Kim
74*17f01e99SJung-uk Kim    [ proxy_ext ]
75*17f01e99SJung-uk Kim    language=id-ppl-anyLanguage
76*17f01e99SJung-uk Kim    pathlen=0
77*17f01e99SJung-uk Kim    policy=text:BC
78*17f01e99SJung-uk Kim
79*17f01e99SJung-uk KimThe policy value has a specific syntax, I<syntag>:I<string>, where the
80*17f01e99SJung-uk KimI<syntag> determines what will be done with the string.  The following
81*17f01e99SJung-uk KimI<syntag>s are recognised:
82*17f01e99SJung-uk Kim
83*17f01e99SJung-uk Kim=over 4
84*17f01e99SJung-uk Kim
85*17f01e99SJung-uk Kim=item B<text>
86*17f01e99SJung-uk Kim
87*17f01e99SJung-uk Kimindicates that the string is a byte sequence, without any encoding:
88*17f01e99SJung-uk Kim
89*17f01e99SJung-uk Kim    policy=text:räksmörgås
90*17f01e99SJung-uk Kim
91*17f01e99SJung-uk Kim=item B<hex>
92*17f01e99SJung-uk Kim
93*17f01e99SJung-uk Kimindicates the string is encoded hexadecimal encoded binary data, with
94*17f01e99SJung-uk Kimcolons between each byte (every second hex digit):
95*17f01e99SJung-uk Kim
96*17f01e99SJung-uk Kim    policy=hex:72:E4:6B:73:6D:F6:72:67:E5:73
97*17f01e99SJung-uk Kim
98*17f01e99SJung-uk Kim=item B<file>
99*17f01e99SJung-uk Kim
100*17f01e99SJung-uk Kimindicates that the text of the policy should be taken from a file.
101*17f01e99SJung-uk KimThe string is then a filename.  This is useful for policies that are
102*17f01e99SJung-uk Kimlarge (more than a few lines, e.g. XML documents).
103*17f01e99SJung-uk Kim
104*17f01e99SJung-uk Kim=back
105*17f01e99SJung-uk Kim
106*17f01e99SJung-uk KimI<NOTE: The proxy policy value is what determines the rights granted
107*17f01e99SJung-uk Kimto the process during the proxy certificate.  It's up to the
108*17f01e99SJung-uk Kimapplication to interpret and combine these policies.>
109*17f01e99SJung-uk Kim
110*17f01e99SJung-uk KimWith a proxy extension, creating a proxy certificate is a matter of
111*17f01e99SJung-uk Kimtwo commands:
112*17f01e99SJung-uk Kim
113*17f01e99SJung-uk Kim    openssl req -new -config proxy.cnf \
114*17f01e99SJung-uk Kim        -out proxy.req -keyout proxy.key \
115*17f01e99SJung-uk Kim        -subj "/DC=org/DC=openssl/DC=users/CN=proxy 1"
116*17f01e99SJung-uk Kim
117*17f01e99SJung-uk Kim    openssl x509 -req -CAcreateserial -in proxy.req -out proxy.crt \
118*17f01e99SJung-uk Kim        -CA user.crt -CAkey user.key -days 7 \
119*17f01e99SJung-uk Kim        -extfile proxy.cnf -extensions v3_proxy1
120*17f01e99SJung-uk Kim
121*17f01e99SJung-uk KimYou can also create a proxy certificate using another proxy
122*17f01e99SJung-uk Kimcertificate as issuer (note: using a different configuration
123*17f01e99SJung-uk Kimsection for the proxy extensions):
124*17f01e99SJung-uk Kim
125*17f01e99SJung-uk Kim    openssl req -new -config proxy.cnf \
126*17f01e99SJung-uk Kim        -out proxy2.req -keyout proxy2.key \
127*17f01e99SJung-uk Kim        -subj "/DC=org/DC=openssl/DC=users/CN=proxy 1/CN=proxy 2"
128*17f01e99SJung-uk Kim
129*17f01e99SJung-uk Kim    openssl x509 -req -CAcreateserial -in proxy2.req -out proxy2.crt \
130*17f01e99SJung-uk Kim        -CA proxy.crt -CAkey proxy.key -days 7 \
131*17f01e99SJung-uk Kim        -extfile proxy.cnf -extensions v3_proxy2
132*17f01e99SJung-uk Kim
133*17f01e99SJung-uk Kim=head2 Using proxy certs in applications
134*17f01e99SJung-uk Kim
135*17f01e99SJung-uk KimTo interpret proxy policies, the application would normally start with
136*17f01e99SJung-uk Kimsome default rights (perhaps none at all), then compute the resulting
137*17f01e99SJung-uk Kimrights by checking the rights against the chain of proxy certificates,
138*17f01e99SJung-uk Kimuser certificate and CA certificates.
139*17f01e99SJung-uk Kim
140*17f01e99SJung-uk KimThe complicated part is figuring out how to pass data between your
141*17f01e99SJung-uk Kimapplication and the certificate validation procedure.
142*17f01e99SJung-uk Kim
143*17f01e99SJung-uk KimThe following ingredients are needed for such processing:
144*17f01e99SJung-uk Kim
145*17f01e99SJung-uk Kim=over 4
146*17f01e99SJung-uk Kim
147*17f01e99SJung-uk Kim=item *
148*17f01e99SJung-uk Kim
149*17f01e99SJung-uk Kima callback function that will be called for every certificate being
150*17f01e99SJung-uk Kimvalidated.  The callback is called several times for each certificate,
151*17f01e99SJung-uk Kimso you must be careful to do the proxy policy interpretation at the
152*17f01e99SJung-uk Kimright time.  You also need to fill in the defaults when the EE
153*17f01e99SJung-uk Kimcertificate is checked.
154*17f01e99SJung-uk Kim
155*17f01e99SJung-uk Kim=item *
156*17f01e99SJung-uk Kim
157*17f01e99SJung-uk Kima data structure that is shared between your application code and the
158*17f01e99SJung-uk Kimcallback.
159*17f01e99SJung-uk Kim
160*17f01e99SJung-uk Kim=item *
161*17f01e99SJung-uk Kim
162*17f01e99SJung-uk Kima wrapper function that sets it all up.
163*17f01e99SJung-uk Kim
164*17f01e99SJung-uk Kim=item *
165*17f01e99SJung-uk Kim
166*17f01e99SJung-uk Kiman ex_data index function that creates an index into the generic
167*17f01e99SJung-uk Kimex_data store that is attached to an X509 validation context.
168*17f01e99SJung-uk Kim
169*17f01e99SJung-uk Kim=back
170*17f01e99SJung-uk Kim
171*17f01e99SJung-uk KimThe following skeleton code can be used as a starting point:
172*17f01e99SJung-uk Kim
173*17f01e99SJung-uk Kim    #include <string.h>
174*17f01e99SJung-uk Kim    #include <netdb.h>
175*17f01e99SJung-uk Kim    #include <openssl/x509.h>
176*17f01e99SJung-uk Kim    #include <openssl/x509v3.h>
177*17f01e99SJung-uk Kim
178*17f01e99SJung-uk Kim    #define total_rights 25
179*17f01e99SJung-uk Kim
180*17f01e99SJung-uk Kim    /*
181*17f01e99SJung-uk Kim     * In this example, I will use a view of granted rights as a bit
182*17f01e99SJung-uk Kim     * array, one bit for each possible right.
183*17f01e99SJung-uk Kim     */
184*17f01e99SJung-uk Kim    typedef struct your_rights {
185*17f01e99SJung-uk Kim        unsigned char rights[(total_rights + 7) / 8];
186*17f01e99SJung-uk Kim    } YOUR_RIGHTS;
187*17f01e99SJung-uk Kim
188*17f01e99SJung-uk Kim    /*
189*17f01e99SJung-uk Kim     * The following procedure will create an index for the ex_data
190*17f01e99SJung-uk Kim     * store in the X509 validation context the first time it's
191*17f01e99SJung-uk Kim     * called.  Subsequent calls will return the same index.
192*17f01e99SJung-uk Kim     */
193*17f01e99SJung-uk Kim    static int get_proxy_auth_ex_data_idx(X509_STORE_CTX *ctx)
194*17f01e99SJung-uk Kim    {
195*17f01e99SJung-uk Kim        static volatile int idx = -1;
196*17f01e99SJung-uk Kim
197*17f01e99SJung-uk Kim        if (idx < 0) {
198*17f01e99SJung-uk Kim            X509_STORE_lock(X509_STORE_CTX_get0_store(ctx));
199*17f01e99SJung-uk Kim            if (idx < 0) {
200*17f01e99SJung-uk Kim                idx = X509_STORE_CTX_get_ex_new_index(0,
201*17f01e99SJung-uk Kim                                                      "for verify callback",
202*17f01e99SJung-uk Kim                                                      NULL,NULL,NULL);
203*17f01e99SJung-uk Kim            }
204*17f01e99SJung-uk Kim            X509_STORE_unlock(X509_STORE_CTX_get0_store(ctx));
205*17f01e99SJung-uk Kim        }
206*17f01e99SJung-uk Kim        return idx;
207*17f01e99SJung-uk Kim    }
208*17f01e99SJung-uk Kim
209*17f01e99SJung-uk Kim    /* Callback to be given to the X509 validation procedure.  */
210*17f01e99SJung-uk Kim    static int verify_callback(int ok, X509_STORE_CTX *ctx)
211*17f01e99SJung-uk Kim    {
212*17f01e99SJung-uk Kim        if (ok == 1) {
213*17f01e99SJung-uk Kim            /*
214*17f01e99SJung-uk Kim             * It's REALLY important you keep the proxy policy check
215*17f01e99SJung-uk Kim             * within this section.  It's important to know that when
216*17f01e99SJung-uk Kim             * ok is 1, the certificates are checked from top to
217*17f01e99SJung-uk Kim             * bottom.  You get the CA root first, followed by the
218*17f01e99SJung-uk Kim             * possible chain of intermediate CAs, followed by the EE
219*17f01e99SJung-uk Kim             * certificate, followed by the possible proxy
220*17f01e99SJung-uk Kim             * certificates.
221*17f01e99SJung-uk Kim             */
222*17f01e99SJung-uk Kim            X509 *xs = X509_STORE_CTX_get_current_cert(ctx);
223*17f01e99SJung-uk Kim
224*17f01e99SJung-uk Kim            if (X509_get_extension_flags(xs) & EXFLAG_PROXY) {
225*17f01e99SJung-uk Kim                YOUR_RIGHTS *rights =
226*17f01e99SJung-uk Kim                    (YOUR_RIGHTS *)X509_STORE_CTX_get_ex_data(ctx,
227*17f01e99SJung-uk Kim                        get_proxy_auth_ex_data_idx(ctx));
228*17f01e99SJung-uk Kim                PROXY_CERT_INFO_EXTENSION *pci =
229*17f01e99SJung-uk Kim                    X509_get_ext_d2i(xs, NID_proxyCertInfo, NULL, NULL);
230*17f01e99SJung-uk Kim
231*17f01e99SJung-uk Kim                switch (OBJ_obj2nid(pci->proxyPolicy->policyLanguage)) {
232*17f01e99SJung-uk Kim                case NID_Independent:
233*17f01e99SJung-uk Kim                    /*
234*17f01e99SJung-uk Kim                     * Do whatever you need to grant explicit rights
235*17f01e99SJung-uk Kim                     * to this particular proxy certificate, usually
236*17f01e99SJung-uk Kim                     * by pulling them from some database.  If there
237*17f01e99SJung-uk Kim                     * are none to be found, clear all rights (making
238*17f01e99SJung-uk Kim                     * this and any subsequent proxy certificate void
239*17f01e99SJung-uk Kim                     * of any rights).
240*17f01e99SJung-uk Kim                     */
241*17f01e99SJung-uk Kim                    memset(rights->rights, 0, sizeof(rights->rights));
242*17f01e99SJung-uk Kim                    break;
243*17f01e99SJung-uk Kim                case NID_id_ppl_inheritAll:
244*17f01e99SJung-uk Kim                    /*
245*17f01e99SJung-uk Kim                     * This is basically a NOP, we simply let the
246*17f01e99SJung-uk Kim                     * current rights stand as they are.
247*17f01e99SJung-uk Kim                     */
248*17f01e99SJung-uk Kim                    break;
249*17f01e99SJung-uk Kim                default:
250*17f01e99SJung-uk Kim                    /*
251*17f01e99SJung-uk Kim                     * This is usually the most complex section of
252*17f01e99SJung-uk Kim                     * code.  You really do whatever you want as long
253*17f01e99SJung-uk Kim                     * as you follow RFC 3820.  In the example we use
254*17f01e99SJung-uk Kim                     * here, the simplest thing to do is to build
255*17f01e99SJung-uk Kim                     * another, temporary bit array and fill it with
256*17f01e99SJung-uk Kim                     * the rights granted by the current proxy
257*17f01e99SJung-uk Kim                     * certificate, then use it as a mask on the
258*17f01e99SJung-uk Kim                     * accumulated rights bit array, and voilà, you
259*17f01e99SJung-uk Kim                     * now have a new accumulated rights bit array.
260*17f01e99SJung-uk Kim                     */
261*17f01e99SJung-uk Kim                    {
262*17f01e99SJung-uk Kim                        int i;
263*17f01e99SJung-uk Kim                        YOUR_RIGHTS tmp_rights;
264*17f01e99SJung-uk Kim                        memset(tmp_rights.rights, 0,
265*17f01e99SJung-uk Kim                               sizeof(tmp_rights.rights));
266*17f01e99SJung-uk Kim
267*17f01e99SJung-uk Kim                        /*
268*17f01e99SJung-uk Kim                         * process_rights() is supposed to be a
269*17f01e99SJung-uk Kim                         * procedure that takes a string and its
270*17f01e99SJung-uk Kim                         * length, interprets it and sets the bits
271*17f01e99SJung-uk Kim                         * in the YOUR_RIGHTS pointed at by the
272*17f01e99SJung-uk Kim                         * third argument.
273*17f01e99SJung-uk Kim                         */
274*17f01e99SJung-uk Kim                        process_rights((char *) pci->proxyPolicy->policy->data,
275*17f01e99SJung-uk Kim                                       pci->proxyPolicy->policy->length,
276*17f01e99SJung-uk Kim                                       &tmp_rights);
277*17f01e99SJung-uk Kim
278*17f01e99SJung-uk Kim                        for(i = 0; i < total_rights / 8; i++)
279*17f01e99SJung-uk Kim                            rights->rights[i] &= tmp_rights.rights[i];
280*17f01e99SJung-uk Kim                    }
281*17f01e99SJung-uk Kim                    break;
282*17f01e99SJung-uk Kim                }
283*17f01e99SJung-uk Kim                PROXY_CERT_INFO_EXTENSION_free(pci);
284*17f01e99SJung-uk Kim            } else if (!(X509_get_extension_flags(xs) & EXFLAG_CA)) {
285*17f01e99SJung-uk Kim                /* We have an EE certificate, let's use it to set default! */
286*17f01e99SJung-uk Kim                YOUR_RIGHTS *rights =
287*17f01e99SJung-uk Kim                    (YOUR_RIGHTS *)X509_STORE_CTX_get_ex_data(ctx,
288*17f01e99SJung-uk Kim                        get_proxy_auth_ex_data_idx(ctx));
289*17f01e99SJung-uk Kim
290*17f01e99SJung-uk Kim                /*
291*17f01e99SJung-uk Kim                 * The following procedure finds out what rights the
292*17f01e99SJung-uk Kim                 * owner of the current certificate has, and sets them
293*17f01e99SJung-uk Kim                 * in the YOUR_RIGHTS structure pointed at by the
294*17f01e99SJung-uk Kim                 * second argument.
295*17f01e99SJung-uk Kim                 */
296*17f01e99SJung-uk Kim                set_default_rights(xs, rights);
297*17f01e99SJung-uk Kim            }
298*17f01e99SJung-uk Kim        }
299*17f01e99SJung-uk Kim        return ok;
300*17f01e99SJung-uk Kim    }
301*17f01e99SJung-uk Kim
302*17f01e99SJung-uk Kim    static int my_X509_verify_cert(X509_STORE_CTX *ctx,
303*17f01e99SJung-uk Kim                                   YOUR_RIGHTS *needed_rights)
304*17f01e99SJung-uk Kim    {
305*17f01e99SJung-uk Kim        int ok;
306*17f01e99SJung-uk Kim        int (*save_verify_cb)(int ok,X509_STORE_CTX *ctx) =
307*17f01e99SJung-uk Kim            X509_STORE_CTX_get_verify_cb(ctx);
308*17f01e99SJung-uk Kim        YOUR_RIGHTS rights;
309*17f01e99SJung-uk Kim
310*17f01e99SJung-uk Kim        X509_STORE_CTX_set_verify_cb(ctx, verify_callback);
311*17f01e99SJung-uk Kim        X509_STORE_CTX_set_ex_data(ctx, get_proxy_auth_ex_data_idx(ctx),
312*17f01e99SJung-uk Kim                                   &rights);
313*17f01e99SJung-uk Kim        X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
314*17f01e99SJung-uk Kim        ok = X509_verify_cert(ctx);
315*17f01e99SJung-uk Kim
316*17f01e99SJung-uk Kim        if (ok == 1) {
317*17f01e99SJung-uk Kim            ok = check_needed_rights(rights, needed_rights);
318*17f01e99SJung-uk Kim        }
319*17f01e99SJung-uk Kim
320*17f01e99SJung-uk Kim        X509_STORE_CTX_set_verify_cb(ctx, save_verify_cb);
321*17f01e99SJung-uk Kim
322*17f01e99SJung-uk Kim        return ok;
323*17f01e99SJung-uk Kim    }
324*17f01e99SJung-uk Kim
325*17f01e99SJung-uk KimIf you use SSL or TLS, you can easily set up a callback to have the
326*17f01e99SJung-uk Kimcertificates checked properly, using the code above:
327*17f01e99SJung-uk Kim
328*17f01e99SJung-uk Kim    SSL_CTX_set_cert_verify_callback(s_ctx, my_X509_verify_cert,
329*17f01e99SJung-uk Kim                                     &needed_rights);
330*17f01e99SJung-uk Kim
331*17f01e99SJung-uk Kim=head1 NOTES
332*17f01e99SJung-uk Kim
333*17f01e99SJung-uk KimTo this date, it seems that proxy certificates have only been used in
334*17f01e99SJung-uk Kimenvironments that are aware of them, and no one seems to have
335*17f01e99SJung-uk Kiminvestigated how they can be used or misused outside of such an
336*17f01e99SJung-uk Kimenvironment.
337*17f01e99SJung-uk Kim
338*17f01e99SJung-uk KimFor that reason, OpenSSL requires that applications aware of proxy
339*17f01e99SJung-uk Kimcertificates must also make that explicit.
340*17f01e99SJung-uk Kim
341*17f01e99SJung-uk KimB<subjectAltName> and B<issuerAltName> are forbidden in proxy
342*17f01e99SJung-uk Kimcertificates, and this is enforced in OpenSSL.  The subject must be
343*17f01e99SJung-uk Kimthe same as the issuer, with one commonName added on.
344*17f01e99SJung-uk Kim
345*17f01e99SJung-uk Kim=head1 SEE ALSO
346*17f01e99SJung-uk Kim
347*17f01e99SJung-uk KimL<X509_STORE_CTX_set_flags(3)>,
348*17f01e99SJung-uk KimL<X509_STORE_CTX_set_verify_cb(3)>,
349*17f01e99SJung-uk KimL<X509_VERIFY_PARAM_set_flags(3)>,
350*17f01e99SJung-uk KimL<SSL_CTX_set_cert_verify_callback(3)>,
351*17f01e99SJung-uk KimL<openssl-req(1)>, L<openssl-x509(1)>,
352*17f01e99SJung-uk KimL<RFC 3820|https://tools.ietf.org/html/rfc3820>
353*17f01e99SJung-uk Kim
354*17f01e99SJung-uk Kim=head1 COPYRIGHT
355*17f01e99SJung-uk Kim
356*17f01e99SJung-uk KimCopyright 2019 The OpenSSL Project Authors. All Rights Reserved.
357*17f01e99SJung-uk Kim
358*17f01e99SJung-uk KimLicensed under the Apache License 2.0 (the "License").  You may not use
359*17f01e99SJung-uk Kimthis file except in compliance with the License.  You can obtain a copy
360*17f01e99SJung-uk Kimin the file LICENSE in the source distribution or at
361*17f01e99SJung-uk KimL<https://www.openssl.org/source/license.html>.
362*17f01e99SJung-uk Kim
363*17f01e99SJung-uk Kim=cut
364