1/* src/scep.h */
2
3#ifndef SCEP_H_
4#define SCEP_H_
5
6#include <stdarg.h>
7#include <string.h>
8#include <libgen.h>
9
10#include <openssl/x509.h>
11#include <openssl/x509v3.h>
12#include <openssl/evp.h>
13#include <openssl/cms.h>
14#include <openssl/pem.h>
15#include <openssl/rand.h>
16#include <openssl/err.h>
17#ifndef OPENSSL_NO_ENGINE
18#include <openssl/engine.h>
19#endif /* OPENSSL_NO_ENGINE */
20
21#define DEFAULT_SIGALG EVP_md5()
22#define DEFAULT_ENCALG EVP_des_cbc()
23#define DEFAULT_VERBOSITY ERROR
24
25#define libscep_VERSION_MAJOR @libscep_VERSION_MAJOR@
26#define libscep_VERSION_MINOR @libscep_VERSION_MINOR@
27#define libscep_STR(x) #x
28#define libscep_VERSION_STR(major, minor) "scep-client v" libscep_STR(major) "." libscep_STR(minor)
29
30#define SCEP_MSG_PKCSREQ_STR "19"
31#define SCEP_MSG_CERTREP_STR "3"
32#define SCEP_MSG_GETCERTINITIAL_STR "20"
33#define SCEP_MSG_GETCERT_STR "21"
34#define SCEP_MSG_GETCRL_STR "22"
35
36#define SCEP_PKISTATUS_SUCCESS "0"
37#define SCEP_PKISTATUS_FAILURE "2"
38#define SCEP_PKISTATUS_PENDING "3"
39
40
41#define SCEP_BAD_ALG_NR "0"
42#define SCEP_BAD_MESSAGE_CHECK_NR "1"
43#define SCEP_BAD_REQUEST_NR "2"
44#define SCEP_BAD_TIME_NR "3"
45#define SCEP_BAD_CERT_ID_NR "4"
46
47// number of nonce bytes, defined by protocol
48#define NONCE_LENGTH 16
49
50#define SCEP_SELFSIGNED_EXPIRE_DAYS 7
51
52#define SCEP_MIME_GETCA_RA "application/x-x509-ca-ra-cert"
53#define SCEP_MIME_GETCA "application/x-x509-ca-cert"
54
55#define scep_log(handle, verbosity, format, ...) \
56    _scep_log(handle, verbosity, __FILE__, __LINE__, format, ##__VA_ARGS__)
57
58#define SCEP_ERR(type, msg, ...)                        \
59    do {                                                \
60        error = type;                                   \
61        if(msg)                                         \
62            scep_log(handle, FATAL, msg, ##__VA_ARGS__);\
63        goto finally;                                   \
64    } while(0)
65
66#define OSSL_ERR(msg, ...)                              \
67    do {                                                \
68        ERR_print_errors(handle->configuration->log);   \
69        SCEP_ERR(SCEPE_OPENSSL, msg, ##__VA_ARGS__);    \
70    } while(0)
71
72typedef enum {
73    FATAL,
74    ERROR,
75    WARN,
76    INFO,
77    DEBUG,
78} SCEP_VERBOSITY;
79
80typedef enum {
81    /* Global options */
82    SCEPCFG_VERBOSITY,
83    SCEPCFG_SIGALG,
84    SCEPCFG_ENCALG,
85    SCEPCFG_LOG,
86
87#ifndef OPENSSL_NO_ENGINE
88    /* Engine stuff */
89    SCEPCFG_ENGINE,
90    SCEPCFG_ENGINE_OBJ,
91    SCEPCFG_ENGINE_PARAM,
92#endif /* OPENSSL_NO_ENGINE */
93
94    /* Flags to be set */
95    SCEPCFG_FLAG_CLEAR, // clear all flags
96    SCEPCFG_FLAG_SET,
97} SCEPCFG_TYPE;
98
99typedef enum {
100    SCEPE_OK,
101    SCEPE_MEMORY,
102    SCEPE_UNKNOWN_CONFIGURATION,
103    SCEPE_UNKOWN_OPERATION,
104    SCEPE_DUPLICATE_BIO,
105    SCEPE_PROTOCOL,
106
107    SCEPE_INVALID_CONTENT,
108    SCEPE_INVALID_PARAMETER,
109    SCEPE_UNHANDLED,
110
111    SCEPE_PARAM,
112
113    SCEPE_NYI,
114    SCEPE_OPENSSL,
115
116    SCEPE_INTERNAL,
117
118    // this always needs to be the last error for unit tests. It is used to
119    // make sure we test all error messages.
120    SCEPE_DUMMY_LAST_ERROR,
121} SCEP_ERROR;
122
123typedef enum {
124    SCEPOP_NONE,
125    SCEPOP_GETCACERT,
126    SCEPOP_PKCSREQ,
127    SCEPOP_GETCERT,
128    SCEPOP_GETCRL,
129    SCEPOP_GETNEXTCACERT,
130    SCEPOP_GETCERTINITIAL,
131    SCEPOP_CERTREP,
132} SCEP_OPERATION;
133
134typedef enum {
135    SCEP_SUCCESS = 0,
136    SCEP_FAILURE = 2,
137    SCEP_PENDING = 3,
138} SCEP_PKISTATUS;
139
140typedef enum {
141    SCEP_BAD_ALG = 0,
142    SCEP_BAD_MESSAGE_CHECK = 1,
143    SCEP_BAD_REQUEST = 2,
144    SCEP_BAD_TIME = 3,
145    SCEP_BAD_CERT_ID = 4,
146} SCEP_FAILINFO;
147
148typedef enum {
149    SCEP_MSG_PKCSREQ = 19,
150    SCEP_MSG_CERTREP = 3,
151    SCEP_MSG_GETCERTINITIAL = 20,
152    SCEP_MSG_GETCERT = 21,
153    SCEP_MSG_GETCRL = 22,
154} SCEP_MESSAGE_TYPE;
155
156typedef enum {
157    SCEP_SKIP_SIGNER_CERT           = 0x0001,
158    SCEP_ALLOW_MULTIPLE_SIGNER_CERT = 0x0002,
159    SCEP_STRICT_SENDER_NONCE        = 0x0004,
160} SCEP_FLAGS;
161
162typedef enum {
163    SCEP_PARAM_SENDERNONCE          = 0x0001,
164} SCEP_PARAM;
165
166#ifndef OPENSSL_NO_ENGINE
167struct engine_params_t {
168    char *name;
169    char *value;
170    struct engine_params_t *next;
171};
172#endif /* OPENSSL_NO_ENGINE */
173
174typedef struct {
175    SCEP_VERBOSITY verbosity;
176    const EVP_MD *sigalg;
177    const EVP_CIPHER *encalg;
178    BIO *log;
179    SCEP_FLAGS flags;
180#ifndef OPENSSL_NO_ENGINE
181    ENGINE *engine;
182    int internal_engine;
183    struct engine_params_t *params;
184#endif /* OPENSSL_NO_ENGINE */
185} SCEP_CONFIGURATION;
186
187typedef struct {
188    int messageType;
189    int pkiStatus;
190    int failInfo;
191    int senderNonce;
192    int recipientNonce;
193    int transId;
194    int extensionReq;
195} SCEP_OIDS;
196
197typedef struct {
198    SCEP_CONFIGURATION *configuration;
199    SCEP_OIDS *oids;
200    SCEP_PARAM params_set;
201    unsigned char senderNonce[NONCE_LENGTH];
202} SCEP;
203
204typedef struct pkcs7_issuer_and_subject_st
205{
206    X509_NAME *issuer;
207    X509_NAME *subject;
208} PKCS7_ISSUER_AND_SUBJECT;
209
210/* public return value containing all relevant values of a request */
211typedef struct {
212    SCEP_PKISTATUS pkiStatus;
213    SCEP_FAILINFO failInfo;
214    char *transactionID;
215    unsigned char senderNonce[NONCE_LENGTH];
216    unsigned char recipientNonce[NONCE_LENGTH];
217    ASN1_TYPE *challenge_password;
218    X509 *signer_certificate;
219    char *messageType_str;
220    SCEP_MESSAGE_TYPE messageType;
221    /* Different types of message content for different operations.
222     * Contains the required data for the specified operation
223     * if there is data attached to the request/response
224     */
225    union {
226        struct {
227            X509_REQ *request;
228            int initialEnrollment;
229        }; /* PKCSReq */
230        PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; /* GetCert */
231        PKCS7_ISSUER_AND_SUBJECT *issuer_and_subject; /* GetCertInitial */
232
233        struct {
234            SCEP_OPERATION request_type;
235            /* CertRep depends on request type */
236            union {
237                STACK_OF(X509) *certs;  /* all except GetCRL response */
238                X509_CRL *crl; /* for GetCRL */
239
240                PKCS7 *messageData; /* internal */
241            };
242        };
243    };
244} SCEP_DATA;
245
246/* internal structure to handle operations */
247struct p7_data_t {
248    PKCS7 *p7;
249    BIO *bio;
250    PKCS7_SIGNER_INFO *signer_info;
251    unsigned char sender_nonce[NONCE_LENGTH];
252    char *transaction_id;
253};
254
255/* External functions */
256SCEP_ERROR scep_init(SCEP **handle);
257void scep_cleanup(SCEP *handle);
258SCEP_ERROR scep_conf_set(SCEP *handle, SCEPCFG_TYPE type, ...);
259SCEP_ERROR scep_param_set(SCEP *handle, SCEP_PARAM type, void *value);
260SCEP_ERROR scep_param_get(SCEP *handle, SCEP_PARAM type, void **value);
261#ifndef OPENSSL_NO_ENGINE
262SCEP_ERROR scep_engine_get(SCEP *handle, ENGINE **e);
263#endif /* OPENSSL_NO_ENGINE */
264char *scep_strerror(SCEP_ERROR err);
265char *scep_fail_info_str(SCEP_FAILINFO fail_info);
266SCEP_ERROR scep_PKCS7_base64_encode(SCEP *handle, PKCS7 *p7, char **encoded);
267SCEP_ERROR scep_new_selfsigned_X509(
268    SCEP *handle, X509_REQ *req, EVP_PKEY *req_key, X509 **cert);
269SCEP_ERROR SCEP_DATA_free(SCEP_DATA *data);
270SCEP_ERROR scep_certrep(
271    SCEP *handle, char *transactionID, unsigned char *senderNonce,
272    SCEP_PKISTATUS pkiStatus, SCEP_FAILINFO failInfo, X509 *requestedCert,
273    X509 *sig_cert, EVP_PKEY *sig_key, X509 *enc_cert,
274    STACK_OF(X509) *additionalCerts, X509_CRL *crl, PKCS7 **pkiMessage);
275SCEP_ERROR scep_pkcsreq(
276    SCEP *handle, X509_REQ *req, X509 *sig_cert, EVP_PKEY *sig_key,
277    X509 *enc_cert, PKCS7 **pkiMessage);
278SCEP_ERROR scep_unwrap(
279    SCEP *handle, PKCS7 *pkiMessage, X509 *ca_cert, X509 *dec_cert,
280    EVP_PKEY *dec_key, SCEP_DATA **output);
281SCEP_ERROR scep_unwrap_response(
282    SCEP *handle, PKCS7 *pkiMessage, X509 *ca_cert,
283    X509 *request_cert, EVP_PKEY *request_key,
284    SCEP_OPERATION request_type, SCEP_DATA **output);
285SCEP_ERROR scep_get_cert_initial(
286    SCEP *handle, X509_REQ *req, X509 *sig_cert, EVP_PKEY *sig_key,
287    X509 *cacert, X509 *enc_cert,
288    PKCS7 **pkiMessage);
289SCEP_ERROR scep_get_cert(
290    SCEP *handle, X509 *sig_cert, EVP_PKEY *sig_key,
291    X509_NAME *issuer, ASN1_INTEGER *serial, X509 *enc_cert,
292    PKCS7 **pkiMessage);
293SCEP_ERROR scep_get_crl(
294    SCEP *handle, X509 *sig_cert, EVP_PKEY *sig_key,
295    X509 *req_cert, X509 *enc_cert,
296    PKCS7 **pkiMessage);
297SCEP_ERROR scep_getcacert_reply(
298	SCEP *handle, STACK_OF(X509) *certs, X509 *signcert,
299	EVP_PKEY *key, PKCS7 **p7);
300
301/* Internal functions */
302
303/* scep.c */
304SCEP_ERROR scep_create_oids(SCEP *);
305
306/* configuration.c */
307SCEP_ERROR scep_conf_init(SCEP *handle);
308void scep_conf_free(SCEP_CONFIGURATION *conf);
309SCEP_ERROR scep_conf_sanity_check(SCEP *handle);
310
311/* util.c */
312SCEP_ERROR scep_calculate_transaction_id_pubkey(
313    SCEP *handle, EVP_PKEY *pubkey, char **transaction_id);
314void _scep_log(SCEP *handle, SCEP_VERBOSITY verbosity, const char *file,
315        int line, char *format, ...);
316SCEP_ERROR scep_calculate_transaction_id_ias_type(
317    SCEP *handle, PKCS7_ISSUER_AND_SERIAL *ias, char *messageType, char **transaction_id);
318int X509_REQ_cmp(X509_REQ *req1, X509_REQ *req2);
319DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SUBJECT)
320
321/* message.c */
322SCEP_ERROR scep_p7_client_init(
323    SCEP *handle, X509 *sig_cert, EVP_PKEY *sig_key,
324    struct p7_data_t *p7data);
325SCEP_ERROR scep_p7_server_init(SCEP *handle, struct p7_data_t *p7data);
326SCEP_ERROR scep_p7_final(SCEP *handle, struct p7_data_t *p7data, PKCS7 **p7);
327
328SCEP_ERROR scep_pkiMessage(
329    SCEP *handle, char *messageType, BIO *data,
330    X509 *enc_cert,
331    struct p7_data_t *p7data);
332#endif /* SCEP_H_ */
333