1 /*
2  * pssl.h
3  *
4  * Secure Sockets Layer channel interface class.
5  *
6  * Portable Windows Library
7  *
8  * Copyright (c) 1993-2002 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Portable Windows Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Contributor(s): ______________________________________.
25  *
26  * $Revision: 25519 $
27  * $Author: rjongbloed $
28  * $Date: 2011-04-06 03:26:18 -0500 (Wed, 06 Apr 2011) $
29  */
30 
31 #ifndef PTLIB_PSSL_H
32 #define PTLIB_PSSL_H
33 
34 #ifdef P_USE_PRAGMA
35 #pragma interface
36 #endif
37 
38 #include <ptlib/sockets.h>
39 
40 
41 struct ssl_st;
42 struct ssl_ctx_st;
43 struct x509_st;
44 struct evp_pkey_st;
45 struct dh_st;
46 
47 enum PSSLFileTypes {
48   PSSLFileTypePEM,
49   PSSLFileTypeASN1,
50   PSSLFileTypeDEFAULT
51 };
52 
53 
54 /**Private key for SSL.
55    This class embodies a common environment for all private keys used by the
56    PSSLContext and PSSLChannel classes.
57   */
58 class PSSLPrivateKey : public PObject
59 {
60   PCLASSINFO(PSSLPrivateKey, PObject);
61   public:
62     /**Create an empty private key.
63       */
64     PSSLPrivateKey();
65 
66     /**Create a new RSA private key.
67       */
68     PSSLPrivateKey(
69       unsigned modulus,   ///< Number of bits
70       void (*callback)(int,int,void *) = NULL,  ///< Progress callback function
71       void *cb_arg = NULL                       ///< Argument passed to callback
72     );
73 
74     /**Create a new private key given the file.
75        The type of the private key can be specified explicitly, or if
76        PSSLFileTypeDEFAULT it will be determined from the file extension,
77        ".pem" is a text file, anything else eg ".der" is a binary ASN1 file.
78       */
79     PSSLPrivateKey(
80       const PFilePath & keyFile,  ///< Private key file
81       PSSLFileTypes fileType = PSSLFileTypeDEFAULT  ///< Type of file to read
82     );
83 
84     /**Create private key from the binary ASN1 DER encoded data specified.
85       */
86     PSSLPrivateKey(
87       const BYTE * keyData,   ///< Private key data
88       PINDEX keySize          ///< Size of private key data
89     );
90 
91     /**Create private key from the binary ASN1 DER encoded data specified.
92       */
93     PSSLPrivateKey(
94       const PBYTEArray & keyData  ///< Private key data
95     );
96 
97     /**Create a copy of the private key.
98       */
99     PSSLPrivateKey(
100       const PSSLPrivateKey & privKey
101     );
102 
103     /**Create a copy of the private key.
104       */
105     PSSLPrivateKey & operator=(
106       const PSSLPrivateKey & privKay
107     );
108 
109     /**Destroy and release storage for private key.
110       */
111     ~PSSLPrivateKey();
112 
113     /**Get internal OpenSSL private key structure.
114       */
115     operator evp_pkey_st *() const { return key; }
116 
117     /**Create a new private key.
118      */
119     PBoolean Create(
120       unsigned modulus,   ///< Number of bits
121       void (*callback)(int,int,void *) = NULL,  ///< Progress callback function
122       void *cb_arg = NULL                       ///< Argument passed to callback
123     );
124 
125     /**Get the certificate as binary ASN1 DER encoded data.
126       */
127     PBYTEArray GetData() const;
128 
129     /**Get the certificate as ASN1 DER base64 encoded data.
130       */
131     PString AsString() const;
132 
133     /**Load private key from file.
134        The type of the private key can be specified explicitly, or if
135        PSSLFileTypeDEFAULT it will be determined from the file extension,
136        ".pem" is a text file, anything else eg ".der" is a binary ASN1 file.
137       */
138     PBoolean Load(
139       const PFilePath & keyFile,  ///< Private key file
140       PSSLFileTypes fileType = PSSLFileTypeDEFAULT  ///< Type of file to read
141     );
142 
143     /**Save private key to file.
144        The type of the private key can be specified explicitly, or if
145        PSSLFileTypeDEFAULT it will be determined from the file extension,
146        ".pem" is a text file, anything else eg ".der" is a binary ASN1 file.
147       */
148     PBoolean Save(
149       const PFilePath & keyFile,  ///< Private key file
150       PBoolean append = false,        ///< Append to file
151       PSSLFileTypes fileType = PSSLFileTypeDEFAULT  ///< Type of file to write
152     );
153 
154 
155   protected:
156     evp_pkey_st * key;
157 };
158 
159 
160 /**Certificate for SSL.
161    This class embodies a common environment for all certificates used by the
162    PSSLContext and PSSLChannel classes.
163   */
164 class PSSLCertificate : public PObject
165 {
166   PCLASSINFO(PSSLCertificate, PObject);
167   public:
168     /**Create an empty certificate.
169       */
170     PSSLCertificate();
171 
172     /**Create a new certificate given the file.
173        The type of the certificate key can be specified explicitly, or if
174        PSSLFileTypeDEFAULT it will be determined from the file extension,
175        ".pem" is a text file, anything else eg ".der" is a binary ASN1 file.
176       */
177     PSSLCertificate(
178       const PFilePath & certFile, ///< Certificate file
179       PSSLFileTypes fileType = PSSLFileTypeDEFAULT  ///< Type of file to read
180     );
181 
182     /**Create certificate from the binary ASN1 DER encoded data specified.
183       */
184     PSSLCertificate(
185       const BYTE * certData,  ///< Certificate data
186       PINDEX certSize        ///< Size of certificate data
187     );
188 
189     /**Create certificate from the binary ASN1 DER encoded data specified.
190       */
191     PSSLCertificate(
192       const PBYTEArray & certData  ///< Certificate data
193     );
194 
195     /**Create certificate from the ASN1 DER base64 encoded data specified.
196       */
197     PSSLCertificate(
198       const PString & certString  ///< Certificate data as string
199     );
200 
201     /**Create a copy of the certificate.
202       */
203     PSSLCertificate(
204       const PSSLCertificate & cert
205     );
206 
207     /**Create a copy of the certificate.
208       */
209     PSSLCertificate & operator=(
210       const PSSLCertificate & cert
211     );
212 
213     /**Destroy and release storage for certificate.
214       */
215     ~PSSLCertificate();
216 
217     /**Get internal OpenSSL X509 structure.
218       */
219     operator x509_st *() const { return certificate; }
220 
221     /**Create a new root certificate.
222        The subject name is a string of the form "/name=value/name=value" where
223        name is a short name for the field and value is a string value for the
224        field for example:
225           "/C=ZA/SP=Western Cape/L=Cape Town/O=Thawte Consulting cc"
226           "/OU=Certification Services Division/CN=Thawte Server CA"
227           "/Email=server-certs@thawte.com"
228      */
229     PBoolean CreateRoot(
230       const PString & subject,    ///< Subject name for certificate
231       const PSSLPrivateKey & key  ///< Key to sign certificate with
232     );
233 
234     /**Get the certificate as binary ASN1 DER encoded data.
235       */
236     PBYTEArray GetData() const;
237 
238     /**Get the certificate as ASN1 DER base64 encoded data.
239       */
240     PString AsString() const;
241 
242     /**Load certificate from file.
243        The type of the certificate key can be specified explicitly, or if
244        PSSLFileTypeDEFAULT it will be determined from the file extension,
245        ".pem" is a text file, anything else eg ".der" is a binary ASN1 file.
246       */
247     PBoolean Load(
248       const PFilePath & certFile, ///< Certificate file
249       PSSLFileTypes fileType = PSSLFileTypeDEFAULT  ///< Type of file to read
250     );
251 
252     /**Save certificate to file.
253        The type of the certificate key can be specified explicitly, or if
254        PSSLFileTypeDEFAULT it will be determined from the file extension,
255        ".pem" is a text file, anything else eg ".der" is a binary ASN1 file.
256       */
257     PBoolean Save(
258       const PFilePath & keyFile,  ///< Certificate key file
259       PBoolean append = false,        ///< Append to file
260       PSSLFileTypes fileType = PSSLFileTypeDEFAULT  ///< Type of file to write
261     );
262 
263 
264   protected:
265     x509_st * certificate;
266 };
267 
268 
269 /**Diffie-Hellman parameters for SSL.
270    This class embodies a set of Diffie Helman parameters as used by
271    PSSLContext and PSSLChannel classes.
272   */
273 class PSSLDiffieHellman : public PObject
274 {
275   PCLASSINFO(PSSLDiffieHellman, PObject);
276   public:
277     /**Create an empty set of Diffie-Hellman parameters.
278       */
279     PSSLDiffieHellman();
280 
281     /**Create a new set of Diffie-Hellman parameters given the file.
282        The type of the file can be specified explicitly, or if
283        PSSLFileTypeDEFAULT it will be determined from the file extension,
284        ".pem" is a text file, anything else eg ".der" is a binary ASN1 file.
285       */
286     PSSLDiffieHellman(
287       const PFilePath & dhFile, ///< Diffie-Hellman parameters file
288       PSSLFileTypes fileType = PSSLFileTypeDEFAULT  ///< Type of file to read
289     );
290 
291     /**Create a set of Diffie-Hellman parameters.
292       */
293     PSSLDiffieHellman(
294       const BYTE * pData, ///< P data
295       PINDEX pSize,       ///< Size of P data
296       const BYTE * gData, ///< G data
297       PINDEX gSize        ///< Size of G data
298     );
299 
300     /**Create a copy of the Diffie-Hellman parameters.
301       */
302     PSSLDiffieHellman(
303       const PSSLDiffieHellman & dh
304     );
305 
306     /**Create a copy of the Diffie-Hellman parameters.
307       */
308     PSSLDiffieHellman & operator=(
309       const PSSLDiffieHellman & dh
310     );
311 
312     /**Destroy and release storage for Diffie-Hellman parameters.
313       */
314     ~PSSLDiffieHellman();
315 
316     /**Get internal OpenSSL DH structure.
317       */
318     operator dh_st *() const { return dh; }
319 
320     /**Load Diffie-Hellman parameters from file.
321        The type of the file can be specified explicitly, or if
322        PSSLFileTypeDEFAULT it will be determined from the file extension,
323        ".pem" is a text file, anything else eg ".der" is a binary ASN1 file.
324       */
325     PBoolean Load(
326       const PFilePath & dhFile, ///< Diffie-Hellman parameters file
327       PSSLFileTypes fileType = PSSLFileTypeDEFAULT  ///< Type of file to read
328     );
329 
330   protected:
331     dh_st * dh;
332 };
333 
334 
335 /**Context for SSL channels.
336    This class embodies a common environment for all connections made via SSL
337    using the PSSLChannel class. It includes such things as the version of SSL
338    and certificates, CA's etc.
339   */
340 class PSSLContext {
341   public:
342     enum Method {
343       SSLv23,
344       SSLv3,
345       TLSv1
346     };
347 
348     /**Create a new context for SSL channels.
349        An optional session ID may be provided in the context. This is used
350        to identify sessions across multiple channels in this context. The
351        session ID is a completely arbitrary block of data. If sessionId is
352        non NULL and idSize is zero, then sessionId is assumed to be a pointer
353        to a C string.
354        The default SSL method is SSLv23
355       */
356     PSSLContext(
357       const void * sessionId = NULL,  ///< Pointer to session ID
358       PINDEX idSize = 0               ///< Size of session ID
359     );
360     PSSLContext(
361       Method method,                  ///< SSL connection method
362       const void * sessionId = NULL,  ///< Pointer to session ID
363       PINDEX idSize = 0               ///< Size of session ID
364     );
365 
366     /**Clean up the SSL context.
367       */
368     ~PSSLContext();
369 
370     /**Get the internal SSL context structure.
371       */
372     operator ssl_ctx_st *() const { return context; }
373 
374     /**Set the path to locate CA certificates.
375       */
376     PBoolean SetCAPath(
377       const PDirectory & caPath   ///< Directory for CA certificates
378     );
379 
380     /**Set the CA certificate file.
381       */
382     PBoolean SetCAFile(
383       const PFilePath & caFile    ///< CA certificate file
384     );
385 
386     /**Use the certificate specified.
387       */
388     PBoolean UseCertificate(
389       const PSSLCertificate & certificate
390     );
391 
392     /**Use the private key specified.
393       */
394     PBoolean UsePrivateKey(
395       const PSSLPrivateKey & key
396     );
397 
398     /**Use the Diffie-Hellman parameters specified.
399       */
400     PBoolean UseDiffieHellman(
401       const PSSLDiffieHellman & dh
402     );
403 
404     /**Set the available ciphers to those listed.
405       */
406     PBoolean SetCipherList(
407       const PString & ciphers   ///< List of cipher names.
408     );
409 
410   protected:
411     void Construct(Method method, const void * sessionId, PINDEX idSize);
412     ssl_ctx_st * context;
413 };
414 
415 
416 /**This class will start a secure SSL based channel.
417   */
418 class PSSLChannel : public PIndirectChannel
419 {
420   PCLASSINFO(PSSLChannel, PIndirectChannel)
421   public:
422     /**Create a new channel given the context.
423        If no context is given a default one is created.
424       */
425     PSSLChannel(
426       PSSLContext * context = NULL,   ///< Context for SSL channel
427       PBoolean autoDeleteContext = false  ///< Flag for context to be automatically deleted.
428     );
429     PSSLChannel(
430       PSSLContext & context           ///< Context for SSL channel
431     );
432 
433     /**Close and clear the SSL channel.
434       */
435     ~PSSLChannel();
436 
437     // Overrides from PChannel
438     virtual PBoolean Read(void * buf, PINDEX len);
439     virtual PBoolean Write(const void * buf, PINDEX len);
440     virtual PBoolean Close();
Shutdown(ShutdownValue)441     virtual PBoolean Shutdown(ShutdownValue) { return true; }
442     virtual PString GetErrorText(ErrorGroup group = NumErrorGroups) const;
443     virtual PBoolean ConvertOSError(int error, ErrorGroup group = LastGeneralError);
444 
445     // New functions
446     /**Accept a new inbound connection (server).
447        This version expects that the indirect channel has already been opened
448        using Open() beforehand.
449       */
450     PBoolean Accept();
451 
452     /**Accept a new inbound connection (server).
453       */
454     PBoolean Accept(
455       PChannel & channel  ///< Channel to attach to.
456     );
457 
458     /**Accept a new inbound connection (server).
459       */
460     PBoolean Accept(
461       PChannel * channel,     ///< Channel to attach to.
462       PBoolean autoDelete = true  ///< Flag for if channel should be automatically deleted.
463     );
464 
465 
466     /**Connect to remote server.
467        This version expects that the indirect channel has already been opened
468        using Open() beforehand.
469       */
470     PBoolean Connect();
471 
472     /**Connect to remote server.
473       */
474     PBoolean Connect(
475       PChannel & channel  ///< Channel to attach to.
476     );
477 
478     /**Connect to remote server.
479       */
480     PBoolean Connect(
481       PChannel * channel,     ///< Channel to attach to.
482       PBoolean autoDelete = true  ///< Flag for if channel should be automatically deleted.
483     );
484 
485     /**Use the certificate specified.
486       */
487     PBoolean UseCertificate(
488       const PSSLCertificate & certificate
489     );
490 
491     /**Use the private key file specified.
492       */
493     PBoolean UsePrivateKey(
494       const PSSLPrivateKey & key
495     );
496 
497     enum VerifyMode {
498       VerifyNone,
499       VerifyPeer,
500       VerifyPeerMandatory,
501     };
502 
503     void SetVerifyMode(
504       VerifyMode mode
505     );
506 
GetContext()507     PSSLContext * GetContext() const { return context; }
508 
509     virtual PBoolean RawSSLRead(void * buf, PINDEX & len);
510 
511   protected:
512     /**This callback is executed when the Open() function is called with
513        open channels. It may be used by descendent channels to do any
514        handshaking required by the protocol that channel embodies.
515 
516        The default behaviour "connects" the channel to the OpenSSL library.
517 
518        @return
519        Returns true if the protocol handshaking is successful.
520      */
521     virtual PBoolean OnOpen();
522 
523   protected:
524     PSSLContext * context;
525     PBoolean          autoDeleteContext;
526     ssl_st      * ssl;
527 };
528 
529 #endif // PTLIB_PSSL_H
530 
531 
532 // End Of File ///////////////////////////////////////////////////////////////
533