summaryrefslogtreecommitdiffstats
path: root/keystore/jni/cert.c
diff options
context:
space:
mode:
Diffstat (limited to 'keystore/jni/cert.c')
-rw-r--r--keystore/jni/cert.c114
1 files changed, 105 insertions, 9 deletions
diff --git a/keystore/jni/cert.c b/keystore/jni/cert.c
index cc36b84..0db28fd 100644
--- a/keystore/jni/cert.c
+++ b/keystore/jni/cert.c
@@ -136,30 +136,126 @@ err:
return ret_code;
}
-int is_pkcs12(const char *buf, int bufLen)
+PKCS12 *get_p12_handle(const char *buf, int bufLen)
{
- int ret = 0;
BIO *bp = NULL;
PKCS12 *p12 = NULL;
- if (!buf || bufLen < 1) goto err;
+ if (!buf || (bufLen < 1) || (buf[0] != 48)) goto err;
bp = BIO_new(BIO_s_mem());
if (!bp) goto err;
- if (buf[0] != 48) goto err; // it is not DER.
-
if (!BIO_write(bp, buf, bufLen)) goto err;
- if ((p12 = d2i_PKCS12_bio(bp, NULL)) != NULL) {
- PKCS12_free(p12);
- ret = 1;
- }
+ p12 = d2i_PKCS12_bio(bp, NULL);
+
err:
if (bp) BIO_free(bp);
+ return p12;
+}
+
+PKCS12_KEYSTORE *get_pkcs12_keystore_handle(const char *buf, int bufLen,
+ const char *passwd)
+{
+ PKCS12_KEYSTORE *p12store = NULL;
+ EVP_PKEY *pkey = NULL;
+ X509 *cert = NULL;
+ STACK_OF(X509) *certs = NULL;
+ PKCS12 *p12 = get_p12_handle(buf, bufLen);
+
+ if (p12 == NULL) return NULL;
+ if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) {
+ LOGE("Can not parse PKCS12 content");
+ PKCS12_free(p12);
+ return NULL;
+ }
+ if ((p12store = malloc(sizeof(PKCS12_KEYSTORE))) == NULL) {
+ if (cert) X509_free(cert);
+ if (pkey) EVP_PKEY_free(pkey);
+ if (certs) sk_X509_free(certs);
+ }
+ p12store->p12 = p12;
+ p12store->pkey = pkey;
+ p12store->cert = cert;
+ p12store->certs = certs;
+ return p12store;
+}
+
+void free_pkcs12_keystore(PKCS12_KEYSTORE *p12store)
+{
+ if (p12store != NULL) {
+ if (p12store->cert) X509_free(p12store->cert);
+ if (p12store->pkey) EVP_PKEY_free(p12store->pkey);
+ if (p12store->certs) sk_X509_free(p12store->certs);
+ free(p12store);
+ }
+}
+
+int is_pkcs12(const char *buf, int bufLen)
+{
+ int ret = 0;
+ PKCS12 *p12 = get_p12_handle(buf, bufLen);
+ if (p12 != NULL) ret = 1;
+ PKCS12_free(p12);
return ret;
}
+static int convert_to_pem(void *data, int is_cert, char *buf, int size)
+{
+ int len = 0;
+ BIO *bio = NULL;
+
+ if (data == NULL) return -1;
+
+ if ((bio = BIO_new(BIO_s_mem())) == NULL) goto err;
+ if (is_cert) {
+ if ((len = PEM_write_bio_X509(bio, (X509*)data)) == 0) {
+ goto err;
+ }
+ } else {
+ if ((len = PEM_write_bio_PrivateKey(bio, (EVP_PKEY *)data, NULL,
+ NULL, 0, NULL, NULL)) == 0) {
+ goto err;
+ }
+ }
+ if (len < size && (len = BIO_read(bio, buf, size - 1)) > 0) {
+ buf[len] = 0;
+ }
+err:
+ if (bio) BIO_free(bio);
+ return (len == 0) ? -1 : 0;
+}
+
+int get_pkcs12_certificate(PKCS12_KEYSTORE *p12store, char *buf, int size)
+{
+ if ((p12store != NULL) && (p12store->cert != NULL)) {
+ return convert_to_pem((void*)p12store->cert, 1, buf, size);
+ }
+ return -1;
+}
+
+int get_pkcs12_private_key(PKCS12_KEYSTORE *p12store, char *buf, int size)
+{
+ if ((p12store != NULL) && (p12store->pkey != NULL)) {
+ return convert_to_pem((void*)p12store->pkey, 0, buf, size);
+ }
+ return -1;
+}
+
+int pop_pkcs12_certs_stack(PKCS12_KEYSTORE *p12store, char *buf, int size)
+{
+ X509 *cert = NULL;
+
+ if ((p12store != NULL) && (p12store->certs != NULL) &&
+ ((cert = sk_X509_pop(p12store->certs)) != NULL)) {
+ int ret = convert_to_pem((void*)cert, 1, buf, size);
+ X509_free(cert);
+ return ret;
+ }
+ return -1;
+}
+
X509* parse_cert(const char *buf, int bufLen)
{
X509 *cert = NULL;