Example #1
0
File: loader.c Project: Lembed/uTLS
/*
 * 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;
}