certificate: extract and import certificate
[siplcs.git] / src / core / sipe-cert-crypto-nss.c
blob94bb4874997c4c6a0b907e1b3fad302c31023342
1 /**
2 * @file sipe-cert-crypto-nss.c
4 * pidgin-sipe
6 * Copyright (C) 2011 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 /**
24 * Certificate routines implementation based on NSS.
27 #include <glib.h>
29 #include "cert.h"
30 #include "cryptohi.h"
31 #include "keyhi.h"
32 #include "pk11pub.h"
34 #include "sipe-backend.h"
35 #include "sipe-cert-crypto.h"
37 struct sipe_cert_crypto {
38 SECKEYPrivateKey *private;
39 SECKEYPublicKey *public;
42 struct sipe_cert_crypto *sipe_cert_crypto_init(void)
44 PK11SlotInfo *slot = PK11_GetInternalKeySlot();
46 if (slot) {
47 PK11RSAGenParams rsaParams;
48 struct sipe_cert_crypto *ssc = g_new0(struct sipe_cert_crypto, 1);
50 /* RSA parameters - should those be configurable? */
51 rsaParams.keySizeInBits = 2048;
52 rsaParams.pe = 65537;
54 SIPE_DEBUG_INFO_NOFORMAT("sipe_cert_crypto_init: generate key pair, this might take a while...");
55 ssc->private = PK11_GenerateKeyPair(slot,
56 CKM_RSA_PKCS_KEY_PAIR_GEN,
57 &rsaParams,
58 &ssc->public,
59 PR_FALSE, /* not permanent */
60 PR_TRUE, /* sensitive */
61 NULL);
62 if (ssc->private) {
63 SIPE_DEBUG_INFO_NOFORMAT("sipe_cert_crypto_init: key pair generated");
64 PK11_FreeSlot(slot);
65 return(ssc);
68 SIPE_DEBUG_ERROR_NOFORMAT("sipe_cert_crypto_init: key generation failed");
69 g_free(ssc);
70 PK11_FreeSlot(slot);
73 return(NULL);
76 void sipe_cert_crypto_free(struct sipe_cert_crypto *ssc)
78 if (ssc) {
79 if (ssc->public)
80 SECKEY_DestroyPublicKey(ssc->public);
81 if (ssc->private)
82 SECKEY_DestroyPrivateKey(ssc->private);
83 g_free(ssc);
87 static gchar *sign_certreq(CERTCertificateRequest *certreq,
88 SECKEYPrivateKey *private)
90 PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
91 gchar *base64 = NULL;
93 if (arena) {
94 SECItem *encoding = SEC_ASN1EncodeItem(arena,
95 NULL,
96 certreq,
97 SEC_ASN1_GET(CERT_CertificateRequestTemplate));
99 if (encoding) {
100 SECOidTag signtag = SEC_GetSignatureAlgorithmOidTag(private->keyType,
101 SEC_OID_UNKNOWN);
103 if (signtag) {
104 SECItem raw;
106 if (!SEC_DerSignData(arena,
107 &raw,
108 encoding->data,
109 encoding->len,
110 private,
111 signtag)) {
113 SIPE_DEBUG_INFO_NOFORMAT("sign_certreq: request signed successfully");
114 base64 = g_base64_encode(raw.data, raw.len);
116 } else {
117 SIPE_DEBUG_ERROR_NOFORMAT("sign_certreq: signing failed");
119 } else {
120 SIPE_DEBUG_ERROR_NOFORMAT("sign_certreq: can't find signature algorithm");
123 /* all memory allocated from "arena"
124 SECITEM_FreeItem(encoding, PR_TRUE); */
125 } else {
126 SIPE_DEBUG_ERROR_NOFORMAT("sign_certreq: can't ASN.1 encode certreq");
129 PORT_FreeArena(arena, PR_TRUE);
130 } else {
131 SIPE_DEBUG_ERROR_NOFORMAT("sign_certreq: can't allocate memory");
134 return(base64);
137 gchar *sipe_cert_crypto_request(struct sipe_cert_crypto *ssc,
138 const gchar *subject)
140 gchar *base64 = NULL;
141 SECItem *pkd;
143 if (!ssc || !subject)
144 return(NULL);
146 pkd = SECKEY_EncodeDERSubjectPublicKeyInfo(ssc->public);
147 if (pkd) {
148 CERTSubjectPublicKeyInfo *spki = SECKEY_DecodeDERSubjectPublicKeyInfo(pkd);
150 if (spki) {
151 gchar *cn = g_strdup_printf("CN=%s", subject);
152 CERTName *name = CERT_AsciiToName(cn);
153 g_free(cn);
155 if (name) {
156 CERTCertificateRequest *certreq = CERT_CreateCertificateRequest(name,
157 spki,
158 NULL);
160 if (certreq) {
161 base64 = sign_certreq(certreq, ssc->private);
162 CERT_DestroyCertificateRequest(certreq);
163 } else {
164 SIPE_DEBUG_ERROR_NOFORMAT("sipe_cert_crypto_create: certreq creation failed");
167 CERT_DestroyName(name);
168 } else {
169 SIPE_DEBUG_ERROR_NOFORMAT("sipe_cert_crypto_create: subject name creation failed");
172 SECKEY_DestroySubjectPublicKeyInfo(spki);
173 } else {
174 SIPE_DEBUG_ERROR_NOFORMAT("sipe_cert_crypto_create: DER decode public key info failed");
177 SECITEM_FreeItem(pkd, PR_TRUE);
178 } else {
179 SIPE_DEBUG_ERROR_NOFORMAT("sipe_cert_crypto_create: DER encode failed");
182 return(base64);
185 void sipe_cert_crypto_destroy(gpointer certificate)
187 CERT_DestroyCertificate(certificate);
190 gpointer sipe_cert_crypto_import(const gchar *base64)
192 return(CERT_ConvertAndDecodeCertificate((char *) base64));
196 Local Variables:
197 mode: c
198 c-file-style: "bsd"
199 indent-tabs-mode: t
200 tab-width: 8
201 End: