/* * Load a file into memory that is in ASCII PEM format. */ static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, int obj_type, SSLObjLoader *ssl_obj, const char *password) { char *start; /* add a null terminator */ ssl_obj->len++; ssl_obj->buf = (uint8_t *)realloc(ssl_obj->buf, ssl_obj->len); ssl_obj->buf[ssl_obj->len - 1] = 0; start = (char *)ssl_obj->buf; return new_pem_obj(ssl_ctx, obj_type == SSL_OBJ_X509_CACERT, start, ssl_obj->len, password); }
/** * Take a base64 blob of data and turn it into its proper ASN.1 form. */ static int new_pem_obj(SSL_CTX *ssl_ctx, int is_cacert, char *where, int remain, const char *password) { int ret = SSL_OK; SSLObjLoader *ssl_obj = NULL; int i, pem_size, obj_type; char *start = NULL, *end = NULL; for (i = 0; i < NUM_PEM_TYPES; i++) { if ((start = strstr(where, begins[i])) && (end = strstr(where, ends[i]))) { remain -= (int)(end-start); start += strlen(begins[i]); pem_size = (int)(end-start); ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader)); /* 4/3 bigger than what we need but so what */ ssl_obj->buf = (uint8_t *)calloc(1, pem_size); if (i == IS_RSA_PRIVATE_KEY && strstr(start, "Proc-Type:") && strstr(start, "4,ENCRYPTED")) { /* check for encrypted PEM file */ if (pem_decrypt(start, end, password, ssl_obj) < 0) goto error; } else if (base64_decode(start, pem_size, ssl_obj->buf, &ssl_obj->len) != 0) goto error; switch (i) { case IS_RSA_PRIVATE_KEY: obj_type = SSL_OBJ_RSA_KEY; break; case IS_ENCRYPTED_PRIVATE_KEY: obj_type = SSL_OBJ_PKCS8; break; case IS_CERTIFICATE: obj_type = is_cacert ? SSL_OBJ_X509_CACERT : SSL_OBJ_X509_CERT; break; default: goto error; } /* In a format we can now understand - so process it */ if ((ret = do_obj(ssl_ctx, obj_type, ssl_obj, password))) goto error; end += strlen(ends[i]); remain -= (int)strlen(ends[i]); while (remain > 0 && (*end == '\r' || *end == '\n')) { end++; remain--; } break; } } if (i == NUM_PEM_TYPES) goto error; /* more PEM stuff to process? */ if (remain) ret = new_pem_obj(ssl_ctx, is_cacert, end, remain, password); error: ssl_obj_free(ssl_obj); return ret; }