Ejemplo n.º 1
0
static bool _cjose_jwe_build_hdr(
        cjose_jwe_t *jwe, 
        cjose_header_t *header,
        cjose_err *err)
{
    // save header object as part of the JWE (and incr. refcount)
    jwe->hdr = header;
    json_incref(jwe->hdr);

    // serialize the header
    char *hdr_str = json_dumps(header, JSON_ENCODE_ANY | JSON_PRESERVE_ORDER);
    if (NULL == hdr_str)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        return false;
    }

    // copy the serialized header to JWE (hdr_str is owned by header object)
    jwe->part[0].raw = (uint8_t *)strdup(hdr_str);
    if (NULL == jwe->part[0].raw)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        cjose_get_dealloc()(hdr_str);
        return false;
    }
    jwe->part[0].raw_len = strlen(hdr_str);
    cjose_get_dealloc()(hdr_str);
    
    return true;
}
Ejemplo n.º 2
0
static bool _EC_private_fields(
        const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
{
    ec_keydata      *keydata = (ec_keydata *)jwk->keydata;
    const BIGNUM    *bnD = EC_KEY_get0_private_key(keydata->key);
    uint8_t         *buffer = NULL;
    char            *b64u = NULL;
    size_t          len = 0,
                    offset = 0;
    json_t          *field = NULL;
    bool            result = false;

    // track expected binary data size
    uint8_t     numsize = _ec_size_for_curve(keydata->crv, err);

    // short circuit if 'd' is NULL or 0
    if (!bnD || BN_is_zero(bnD))
    {
        return true;
    }

    buffer = cjose_get_alloc()(numsize);
    if (!buffer)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto _ec_to_string_cleanup;
    }

    offset = numsize - BN_num_bytes(bnD);
    memset(buffer, 0, numsize);
    BN_bn2bin(bnD, (buffer + offset));
    if (!cjose_base64url_encode(buffer, numsize, &b64u, &len, err))
    {
        goto _ec_to_string_cleanup;
    }
    field = json_stringn(b64u, len);
    if (!field)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto _ec_to_string_cleanup;
    }
    json_object_set(json, "d", field);
    json_decref(field);
    field = NULL;
    cjose_get_dealloc()(b64u);
    b64u = NULL;

    result = true;

    _ec_to_string_cleanup:
    if (buffer)
    {
        cjose_get_dealloc()(buffer);
    }

    return result;
}
Ejemplo n.º 3
0
static void _oct_free(cjose_jwk_t *jwk)
{
    uint8_t *   buffer = (uint8_t *)jwk->keydata;
    jwk->keydata =  NULL;
    if (buffer)
    {
        cjose_get_dealloc()(buffer);
    }
    cjose_get_dealloc()(jwk);
}
Ejemplo n.º 4
0
static inline bool _RSA_json_field(
        BIGNUM *param, const char *name, json_t *json, cjose_err *err)
{
    json_t      *field = NULL;
    uint8_t     *data = NULL;
    char        *b64u = NULL;
    size_t      datalen = 0,
                b64ulen = 0;
    bool        result = false;

    if (!param)
    {
        return true;
    }

    datalen = BN_num_bytes(param);
    data = cjose_get_alloc()(sizeof(uint8_t) * datalen);
    if (!data)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto RSA_json_field_cleanup;
    }
    BN_bn2bin(param, data);
    if (!cjose_base64url_encode(data, datalen, &b64u, &b64ulen, err))
    {
        goto RSA_json_field_cleanup;
    }
    field = json_stringn(b64u, b64ulen);
    if (!field)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto RSA_json_field_cleanup;
    }
    json_object_set(json, name, field);
    json_decref(field);
    field = NULL;
    result = true;

    RSA_json_field_cleanup:
    if (b64u)
    {
        cjose_get_dealloc()(b64u);
        b64u = NULL;
    }
    if (data)
    {
        cjose_get_dealloc()(data);
        data = NULL;
    }

    return result;
}
Ejemplo n.º 5
0
/*
 * perform compact serialization on a JWT and return the resulting string
 */
char *oidc_jwt_serialize(apr_pool_t *pool, oidc_jwt_t *jwt,
		oidc_jose_error_t *err) {
	cjose_err cjose_err;
	const char *cser = NULL;
	if (strcmp(jwt->header.alg, "none") != 0) {
		if (cjose_jws_export(jwt->cjose_jws, &cser, &cjose_err) == FALSE) {
			oidc_jose_error(err, "cjose_jws_export failed: %s",
					oidc_cjose_e2s(pool, cjose_err));
			return NULL;
		}
	} else {

		char *s_payload = json_dumps(jwt->payload.value.json,
				JSON_PRESERVE_ORDER | JSON_COMPACT);

		char *out = NULL;
		size_t out_len;
		if (cjose_base64url_encode((const uint8_t *)s_payload, strlen(s_payload), &out, &out_len,
				&cjose_err) == FALSE)
			return FALSE;
		cser = apr_pstrndup(pool, out, out_len);
		cjose_get_dealloc()(out);

		free(s_payload);

		cser = apr_psprintf(pool, "eyJhbGciOiJub25lIn0.%s.", cser);
	}
	return apr_pstrdup(pool, cser);
}
Ejemplo n.º 6
0
static bool _oct_private_fields(
        const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
{
    json_t *field = NULL;
    char *k = NULL;
    size_t klen = 0;
    uint8_t *keydata = (uint8_t *)jwk->keydata;
    size_t keysize = jwk->keysize / 8;

    if (!cjose_base64url_encode(keydata, keysize, &k, &klen, err))
    {
        return false;
    }

    field = json_stringn(k, klen);
    cjose_get_dealloc()(k);
    k = NULL;
    if (!field)
    {
        return false;
    }
    json_object_set(json, "k", field);
    json_decref(field);
    
    return true;
}
Ejemplo n.º 7
0
static cjose_jwk_t *_cjose_jwk_import_oct(json_t *jwk_json, cjose_err *err)
{
    cjose_jwk_t *jwk = NULL;
    uint8_t *k_buffer = NULL;

    // get the decoded value of k (buflen = 0 means no particular expected len) 
    size_t k_buflen = 0;
    if (!_decode_json_object_base64url_attribute(
            jwk_json, CJOSE_JWK_K_STR, &k_buffer, &k_buflen, err))
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        goto import_oct_cleanup;
    }

    // create the jwk
    jwk = cjose_jwk_create_oct_spec(k_buffer, k_buflen, err);

    import_oct_cleanup:
    if (NULL != k_buffer)
    {
        cjose_get_dealloc()(k_buffer);
    }

    return jwk;
}
Ejemplo n.º 8
0
static bool _cjose_jwe_malloc(
        size_t bytes, bool random, 
        uint8_t **buffer,
        cjose_err *err)
{
    *buffer = (uint8_t *)cjose_get_alloc()(bytes);
    if (NULL == *buffer)
    {   
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        return false;
    }   
    if (random)
    {   
        if (RAND_bytes((unsigned char *)*buffer, bytes) != 1)
        {   
            cjose_get_dealloc()(*buffer);
            CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
            return false;
        }   
    }   
    else
    {   
        memset(*buffer, 0, bytes);
    }   
    return true;
}
Ejemplo n.º 9
0
/*
 * encrypt JWT
 */
apr_byte_t oidc_jwt_encrypt(apr_pool_t *pool, oidc_jwt_t *jwe, oidc_jwk_t *jwk,
		const char *payload, char **serialized, oidc_jose_error_t *err) {

	cjose_header_t *hdr = (cjose_header_t *)jwe->header.value.json;

	if (jwe->header.alg)
		oidc_jwt_hdr_set(jwe, CJOSE_HDR_ALG, jwe->header.alg);
	if (jwe->header.kid)
		oidc_jwt_hdr_set(jwe, CJOSE_HDR_KID, jwe->header.kid);
	if (jwe->header.enc)
		oidc_jwt_hdr_set(jwe, CJOSE_HDR_ENC, jwe->header.enc);

	cjose_err cjose_err;
	cjose_jwe_t *cjose_jwe = cjose_jwe_encrypt(jwk->cjose_jwk, hdr,
			(const uint8_t *) payload, strlen(payload), &cjose_err);
	if (cjose_jwe == NULL) {
		oidc_jose_error(err, "cjose_jwe_encrypt failed: %s",
				oidc_cjose_e2s(pool, cjose_err));
		return FALSE;
	}

	char *cser = cjose_jwe_export(cjose_jwe, &cjose_err);
	if (cser == NULL) {
		oidc_jose_error(err, "cjose_jwe_export failed: %s",
				oidc_cjose_e2s(pool, cjose_err));
		return FALSE;
	}

	*serialized = apr_pstrdup(pool, cser);
	cjose_get_dealloc()(cser);
	cjose_jwe_release(cjose_jwe);

	return TRUE;
}
Ejemplo n.º 10
0
static void _EC_free(cjose_jwk_t *jwk)
{
    ec_keydata  *keydata = (ec_keydata *)jwk->keydata;
    jwk->keydata = NULL;

    if (keydata)
    {
        EC_KEY  *ec = keydata->key;
        keydata->key = NULL;
        if (ec)
        {
            EC_KEY_free(ec);
        }
        cjose_get_dealloc()(keydata);
    }
    cjose_get_dealloc()(jwk);
}
Ejemplo n.º 11
0
static void _RSA_free(cjose_jwk_t *jwk)
{
    RSA *rsa = (RSA *)jwk->keydata;
    jwk->keydata = NULL;
    if (rsa)
    {
        RSA_free(rsa);
    }
    cjose_get_dealloc()(jwk);
}
Ejemplo n.º 12
0
static bool _cjose_jwe_set_cek_a256gcm(
        cjose_jwe_t *jwe, 
        const cjose_jwk_t *jwk,
        cjose_err *err)
{
    // 256 bits = 32 bytes
    static const size_t keysize = 32;

    // if no JWK is provided, generate a random key
    if (NULL == jwk)
    {
        cjose_get_dealloc()(jwe->cek);
        if (!_cjose_jwe_malloc(keysize, true, &jwe->cek, err))
        {
            return false;
        }   
        jwe->cek_len = keysize;
    }
    else
    {
        // if a JWK is provided, it must be a symmetric key of correct size
        if (CJOSE_JWK_KTY_OCT != cjose_jwk_get_kty(jwk, err) ||
                jwk->keysize != keysize*8 ||
                NULL == jwk->keydata)
        {
            CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
            return false;
        }

        // copy the key material directly from jwk to the jwe->cek
        cjose_get_dealloc()(jwe->cek);
        if (!_cjose_jwe_malloc(keysize, false, &jwe->cek, err))
        {
            return false;
        }   
        memcpy(jwe->cek, jwk->keydata, keysize);
        jwe->cek_len = keysize;
    }

    return true;
}
Ejemplo n.º 13
0
void cjose_jwe_release(
        cjose_jwe_t *jwe)
{
    if (NULL == jwe)
    {
        return;
    }
    if (NULL != jwe->hdr)
    {
        json_decref(jwe->hdr);
    }

    for (int i = 0; i < 5; ++i)
    {
        cjose_get_dealloc()(jwe->part[i].raw);
        cjose_get_dealloc()(jwe->part[i].b64u);
    }
    cjose_get_dealloc()(jwe->cek);
    cjose_get_dealloc()(jwe->dat);
    cjose_get_dealloc()(jwe);
}
Ejemplo n.º 14
0
static bool _cjose_jwe_set_iv_a256gcm(
        cjose_jwe_t *jwe,
        cjose_err *err)
{
    // generate IV as random 96 bit value
    cjose_get_dealloc()(jwe->part[2].raw);
    jwe->part[2].raw_len = 12;
    if (!_cjose_jwe_malloc(jwe->part[2].raw_len, true, &jwe->part[2].raw, err))
    {
        return false;
    }

    return true;
}
Ejemplo n.º 15
0
static bool _cjose_jwe_encrypt_ek_rsa_oaep(
        cjose_jwe_t *jwe, 
        const cjose_jwk_t *jwk,
        cjose_err *err)
{
    // jwk must be RSA and have the necessary public parts set
    if (jwk->kty != CJOSE_JWK_KTY_RSA ||
        NULL == jwk->keydata ||
        NULL == ((RSA *)jwk->keydata)->e || 
        NULL == ((RSA *)jwk->keydata)->n)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        return false;
    }

    // generate random cek
    if (!jwe->fns.set_cek(jwe, NULL, err))
    {
        return false;
    }   

    // the size of the ek will match the size of the RSA key
    jwe->part[1].raw_len = RSA_size((RSA *)jwk->keydata);

    // for OAEP padding - the RSA size - 41 must be greater than input
    if (jwe->cek_len >= jwe->part[1].raw_len - 41)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        return false;        
    }

    // allocate memory for RSA encryption
    cjose_get_dealloc()(jwe->part[1].raw);
    if (!_cjose_jwe_malloc(jwe->part[1].raw_len, false, &jwe->part[1].raw, err))
    {
        return false;        
    }

    // encrypt the CEK using RSAES-OAEP
    if (RSA_public_encrypt(jwe->cek_len, jwe->cek, jwe->part[1].raw,
            (RSA *)jwk->keydata, RSA_PKCS1_OAEP_PADDING) != 
            jwe->part[1].raw_len)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        return false;        
    }

    return true;
}
Ejemplo n.º 16
0
Archivo: jws.c Proyecto: cisco/cjose
void cjose_jws_release(cjose_jws_t *jws)
{
    if (NULL == jws)
    {
        return;
    }

    if (NULL != jws->hdr)
    {
        json_decref(jws->hdr);
    }

    cjose_get_dealloc()(jws->hdr_b64u);
    cjose_get_dealloc()(jws->dat);
    cjose_get_dealloc()(jws->dat_b64u);
    cjose_get_dealloc()(jws->dig);
    cjose_get_dealloc()(jws->sig);
    cjose_get_dealloc()(jws->sig_b64u);
    cjose_get_dealloc()(jws->cser);
    cjose_get_dealloc()(jws);
}
Ejemplo n.º 17
0
cjose_jwk_t *cjose_jwk_create_oct_random(size_t keysize, cjose_err *err)
{
    cjose_jwk_t *           jwk = NULL;
    uint8_t *               buffer = NULL;

    if (0 == keysize)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        goto create_oct_failed;
    }

    // resize to bytes
    size_t buffersize = sizeof(uint8_t) * (keysize / 8);

    buffer = (uint8_t *)cjose_get_alloc()(buffersize);
    if (NULL == buffer)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto create_oct_failed;
    }
    if (1 != RAND_bytes(buffer, buffersize))
    {
        goto create_oct_failed;
    }

    jwk = _oct_new(buffer, keysize, err);
    if (NULL == jwk)
    {
        goto create_oct_failed;
    }
    return jwk;

    create_oct_failed:
    if (buffer)
    {
        cjose_get_dealloc()(buffer);
        buffer = NULL;
    }

    return NULL;
}
Ejemplo n.º 18
0
bool cjose_jwk_release(cjose_jwk_t *jwk)
{
    if (!jwk)
    {
        return false;
    }

    --(jwk->retained);
    if (0 == jwk->retained)
    {
        cjose_get_dealloc()(jwk->kid);
        jwk->kid = NULL;

        // assumes freefunc is set
        assert(NULL != jwk->fns->free);
        jwk->fns->free(jwk);
        jwk = NULL;
    }

    return (NULL != jwk);
}
Ejemplo n.º 19
0
/*
 * hash a sequence of bytes with a specific algorithm and return the result as a base64url-encoded \0 terminated string
 */
static apr_byte_t oidc_jose_hash_and_base64url_encode(apr_pool_t *pool,
		const char *openssl_hash_algo, const char *input, int input_len,
		char **output) {
	oidc_jose_error_t err;
	unsigned char *hashed = NULL;
	unsigned int hashed_len = 0;
	if (oidc_jose_hash_bytes(pool, openssl_hash_algo,
			(const unsigned char *) input, input_len, &hashed, &hashed_len,
			&err) == FALSE) {
		return FALSE;
	}
	char *out = NULL;
	size_t out_len;
	cjose_err cjose_err;
	if (cjose_base64url_encode(hashed, hashed_len, &out, &out_len,
			&cjose_err) == FALSE)
		return FALSE;
	*output = apr_pstrndup(pool, out, out_len);
	cjose_get_dealloc()(out);
	return TRUE;
}
Ejemplo n.º 20
0
cjose_jwk_t *cjose_jwk_create_EC_random(cjose_jwk_ec_curve crv, cjose_err *err)
{
    cjose_jwk_t *   jwk = NULL;
    EC_KEY *        ec = NULL;

    ec = EC_KEY_new_by_curve_name(crv);
    if (!ec)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        goto create_EC_failed;
    }
    
    if (1 != EC_KEY_generate_key(ec))
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto create_EC_failed;
    }

    jwk = _EC_new(crv, ec, err);
    if (!jwk)
    {
        goto create_EC_failed;
    }

    return jwk;

    create_EC_failed:
    if (jwk)
    {
        cjose_get_dealloc()(jwk);
        jwk = NULL;
    }
    if (ec)
    {
        EC_KEY_free(ec);
        ec = NULL;
    }

    return NULL;
}
Ejemplo n.º 21
0
static bool _cjose_jwe_decrypt_ek_rsa_oaep(
        cjose_jwe_t *jwe, 
        const cjose_jwk_t *jwk,
        cjose_err *err)
{
    if (NULL == jwe || NULL == jwk)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        return false;
    }

    // jwk must be RSA
    if (jwk->kty != CJOSE_JWK_KTY_RSA)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        return false;        
    }

    // we don't know the size of the key to expect, but must be < RSA_size
    cjose_get_dealloc()(jwe->cek);
    size_t buflen = RSA_size((RSA *)jwk->keydata);
    if (!_cjose_jwe_malloc(buflen, false, &jwe->cek, err))
    {
        return false;
    }

    // decrypt the CEK using RSAES-OAEP
    jwe->cek_len = RSA_private_decrypt(
            jwe->part[1].raw_len, jwe->part[1].raw, jwe->cek, 
            (RSA *)jwk->keydata, RSA_PKCS1_OAEP_PADDING);
    if (-1 == jwe->cek_len)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        return false;
    }

    return true;
}
Ejemplo n.º 22
0
/*
 * decrypt a JSON Web Token
 */
apr_byte_t oidc_jwe_decrypt(apr_pool_t *pool, const char *input_json,
		apr_hash_t *keys, char **s_json, oidc_jose_error_t *err, apr_byte_t import_must_succeed) {
	cjose_err cjose_err;
	cjose_jwe_t *jwe = cjose_jwe_import(input_json, strlen(input_json),
			&cjose_err);
	if (jwe != NULL) {
		size_t content_len = 0;
		uint8_t *decrypted = oidc_jwe_decrypt_impl(pool, jwe, keys, &content_len,
				err);
		if (decrypted != NULL) {
			decrypted[content_len] = '\0';
			*s_json = apr_pstrdup(pool, (const char *) decrypted);
			cjose_get_dealloc()(decrypted);
		}
		cjose_jwe_release(jwe);
	} else if (import_must_succeed == FALSE) {
		*s_json = apr_pstrdup(pool, input_json);
	} else {
		oidc_jose_error(err, "cjose_jwe_import failed: %s",
				oidc_cjose_e2s(pool, cjose_err));
	}
	return (*s_json != NULL);
}
Ejemplo n.º 23
0
cjose_jwk_t * cjose_jwk_create_oct_spec(
        const uint8_t *data, size_t len, cjose_err *err)
{
    cjose_jwk_t *           jwk = NULL;
    uint8_t *               buffer = NULL;

    if (NULL == data || 0 == len)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        goto create_oct_failed;
    }

    buffer = (uint8_t *)cjose_get_alloc()(len);
    if (!buffer)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto create_oct_failed;
    }
    memcpy(buffer, data, len);

    jwk = _oct_new(buffer, len * 8, err);
    if (NULL == jwk)
    {
        goto create_oct_failed;
    }

    return jwk;

    create_oct_failed:
    if (buffer)
    {
        cjose_get_dealloc()(buffer);
        buffer = NULL;
    }

    return NULL;
}
Ejemplo n.º 24
0
static cjose_jwk_t *_EC_new(cjose_jwk_ec_curve crv, EC_KEY *ec, cjose_err *err)
{
    ec_keydata *keydata = cjose_get_alloc()(sizeof(ec_keydata));
    if (!keydata)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        return NULL;
    }
    keydata->crv = crv;
    keydata->key = ec;

    cjose_jwk_t *jwk = cjose_get_alloc()(sizeof(cjose_jwk_t));
    if (!jwk)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        cjose_get_dealloc()(keydata);
        return NULL;
    }
    memset(jwk, 0, sizeof(cjose_jwk_t));
    jwk->retained = 1;
    jwk->kty = CJOSE_JWK_KTY_EC;
    switch (crv) {
        case CJOSE_JWK_EC_P_256:
            jwk->keysize = 256;
            break;
        case CJOSE_JWK_EC_P_384:
            jwk->keysize = 384;
            break;
        case CJOSE_JWK_EC_P_521:
            jwk->keysize = 521;
            break;
    }
    jwk->keydata = keydata;
    jwk->fns = &EC_FNTABLE;

    return jwk;
}
Ejemplo n.º 25
0
bool cjose_jwk_set_kid(
        cjose_jwk_t *jwk, 
        const char *kid, 
        size_t len, 
        cjose_err *err)
{
    if (!jwk || !kid)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        return false;
    }
    if (jwk->kid)
    {
        cjose_get_dealloc()(jwk->kid);
    }    
    jwk->kid = (char *)cjose_get_alloc()(len+1);
    if (!jwk->kid)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        return false;
    }
    strncpy(jwk->kid, kid, len+1);
    return true;
}
Ejemplo n.º 26
0
char *cjose_jwk_to_json(const cjose_jwk_t *jwk, bool priv, cjose_err *err)
{
    char *result = NULL;

    if (!jwk)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        return NULL;
    }

    json_t *json = json_object(),
                *field = NULL;
    if (!json)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto to_json_cleanup;
    }

    // set kty
    const char *kty = cjose_jwk_name_for_kty(jwk->kty, err);
    field = json_string(kty);
    if (!field)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto to_json_cleanup;
    }
    json_object_set(json, "kty", field);
    json_decref(field);
    field = NULL;

    // set kid
    if (NULL != jwk->kid)
    {
        field = json_string(jwk->kid);
        if (!field)
        {
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
            goto to_json_cleanup;
        }
        json_object_set(json, CJOSE_JWK_KID_STR, field);
        json_decref(field);
        field = NULL;
    }

    // set public fields
    if (jwk->fns->public_json && !jwk->fns->public_json(jwk, json, err))
    {
        goto to_json_cleanup;
    }

    // set private fields
    if (priv && jwk->fns->private_json && 
            !jwk->fns->private_json(jwk, json, err))
    {
        goto to_json_cleanup;
    }

    // generate the string ...
    char *str_jwk = json_dumps(
            json, JSON_ENCODE_ANY | JSON_COMPACT | JSON_PRESERVE_ORDER);
    if (!str_jwk)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto to_json_cleanup;
    }
    result = strdup(str_jwk);
    cjose_get_dealloc()(str_jwk);
    
    to_json_cleanup:
    if (json)
    {
        json_decref(json);
        json = NULL;
    }
    if (field)
    {
        json_decref(field);
        field = NULL;
    }
    
    return result;
}
Ejemplo n.º 27
0
static bool _cjose_jwe_decrypt_dat_a256gcm(
        cjose_jwe_t *jwe, 
        cjose_err *err)
{
    EVP_CIPHER_CTX *ctx = NULL;

    // get A256GCM cipher
    const EVP_CIPHER *cipher = EVP_aes_256_gcm();
    if (NULL == cipher)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_decrypt_dat_a256gcm_fail;
    }

    // instantiate and initialize a new openssl cipher context
    ctx = EVP_CIPHER_CTX_new();
    if (NULL == ctx)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_decrypt_dat_a256gcm_fail;
    }
    EVP_CIPHER_CTX_init(ctx);

    // initialize context for decryption using A256GCM cipher and CEK and IV
    if (EVP_DecryptInit_ex(ctx, cipher, NULL, jwe->cek, jwe->part[2].raw) != 1)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_decrypt_dat_a256gcm_fail;
    }

    // set the expected GCM-mode authentication tag
    if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 
            jwe->part[4].raw_len, jwe->part[4].raw) != 1)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_decrypt_dat_a256gcm_fail;
    }

    // set GCM mode AAD data (hdr_b64u) by setting "out" to NULL
    int bytes_decrypted = 0;
    if (EVP_DecryptUpdate(ctx, 
                NULL, &bytes_decrypted, 
                (unsigned char *)jwe->part[0].b64u, 
                jwe->part[0].b64u_len) != 1 ||
                bytes_decrypted != jwe->part[0].b64u_len)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_decrypt_dat_a256gcm_fail;
    }

    // allocate buffer for the plaintext
    cjose_get_dealloc()(jwe->dat);
    jwe->dat_len = jwe->part[3].raw_len;
    if (!_cjose_jwe_malloc(jwe->dat_len, false, &jwe->dat, err))
    {
        goto _cjose_jwe_decrypt_dat_a256gcm_fail;
    }

    // decrypt ciphertext to plaintext buffer
    if (EVP_DecryptUpdate(ctx, 
            jwe->dat, &bytes_decrypted, 
            jwe->part[3].raw, jwe->part[3].raw_len) != 1)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_decrypt_dat_a256gcm_fail;
    }
    jwe->dat_len = bytes_decrypted;

    // finalize the encryption
    if (EVP_DecryptFinal_ex(ctx, NULL, &bytes_decrypted) != 1)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_decrypt_dat_a256gcm_fail;
    }

    EVP_CIPHER_CTX_free(ctx);
    return true;

    _cjose_jwe_decrypt_dat_a256gcm_fail:
    if (NULL != ctx)
    {
        EVP_CIPHER_CTX_free(ctx);
    }
    return false;
}
Ejemplo n.º 28
0
static bool _cjose_jwe_encrypt_dat_a256gcm(
        cjose_jwe_t *jwe, 
        const uint8_t *plaintext,
        size_t plaintext_len,
        cjose_err *err)
{
    EVP_CIPHER_CTX *ctx = NULL;

    if (NULL == plaintext)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        goto _cjose_jwe_encrypt_dat_fail;        
    }

    // get A256GCM cipher
    const EVP_CIPHER *cipher = EVP_aes_256_gcm();
    if (NULL == cipher)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_encrypt_dat_fail;
    }

    // instantiate and initialize a new openssl cipher context
    ctx = EVP_CIPHER_CTX_new();
    if (NULL == ctx)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_encrypt_dat_fail;
    }
    EVP_CIPHER_CTX_init(ctx);

    // initialize context for encryption using A256GCM cipher and CEK and IV
    if (EVP_EncryptInit_ex(ctx, cipher, NULL, jwe->cek, jwe->part[2].raw) != 1)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_encrypt_dat_fail;
    }

    // we need the header in base64url encoding as input for encryption
    if ((NULL == jwe->part[0].b64u) && (!cjose_base64url_encode(
        (const uint8_t *)jwe->part[0].raw, jwe->part[0].raw_len, 
        &jwe->part[0].b64u, &jwe->part[0].b64u_len, err)))
    {
        goto _cjose_jwe_encrypt_dat_fail;
    }    

    // set GCM mode AAD data (hdr_b64u) by setting "out" to NULL
    int bytes_encrypted = 0;
    if (EVP_EncryptUpdate(ctx, 
                NULL, &bytes_encrypted, 
                (unsigned char *)jwe->part[0].b64u, 
                jwe->part[0].b64u_len) != 1 ||
                bytes_encrypted != jwe->part[0].b64u_len)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_encrypt_dat_fail;
    }

    // allocate buffer for the ciphertext
    cjose_get_dealloc()(jwe->part[3].raw);
    jwe->part[3].raw_len = plaintext_len;
    if (!_cjose_jwe_malloc(jwe->part[3].raw_len, false, &jwe->part[3].raw, err))
    {
        goto _cjose_jwe_encrypt_dat_fail;        
    }

    // encrypt entire plaintext to ciphertext buffer
    if (EVP_EncryptUpdate(ctx, 
            jwe->part[3].raw, &bytes_encrypted, 
            plaintext, plaintext_len) != 1)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_encrypt_dat_fail;
    }
    jwe->part[3].raw_len = bytes_encrypted;

    // finalize the encryption and set the ciphertext length to correct value
    if (EVP_EncryptFinal_ex(ctx, NULL, &bytes_encrypted) != 1)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_encrypt_dat_fail;
    }

    // allocate buffer for the authentication tag
    cjose_get_dealloc()(jwe->part[4].raw);
    jwe->part[4].raw_len = 16;
    if (!_cjose_jwe_malloc(jwe->part[4].raw_len, false, &jwe->part[4].raw, err))
    {
        goto _cjose_jwe_encrypt_dat_fail;        
    }

    // get the GCM-mode authentication tag
    if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 
            jwe->part[4].raw_len, jwe->part[4].raw) != 1)
    {
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
        goto _cjose_jwe_encrypt_dat_fail;
    }

    EVP_CIPHER_CTX_free(ctx);
    return true;

    _cjose_jwe_encrypt_dat_fail:
    if (NULL != ctx)
    {
        EVP_CIPHER_CTX_free(ctx);
    }
    return false;
}
Ejemplo n.º 29
0
static bool _EC_public_fields(
        const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
{
    ec_keydata      *keydata = (ec_keydata *)jwk->keydata;
    const EC_GROUP  *params = NULL;
    const EC_POINT  *pub = NULL;
    BIGNUM          *bnX = NULL,
                    *bnY = NULL;
    uint8_t         *buffer = NULL;
    char            *b64u = NULL;
    size_t          len = 0,
                    offset = 0;
    json_t          *field = NULL;
    bool            result = false;

    // track expected binary data size
    uint8_t     numsize = _ec_size_for_curve(keydata->crv, err);

    // output the curve
    field = json_string(_ec_name_for_curve(keydata->crv, err));
    if (!field)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto _ec_to_string_cleanup;
    }
    json_object_set(json, "crv", field);
    json_decref(field);
    field = NULL;

    // obtain the public key
    pub = EC_KEY_get0_public_key(keydata->key);
    params = EC_KEY_get0_group(keydata->key);
    if (!pub || !params)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        goto _ec_to_string_cleanup;
    }

    buffer = cjose_get_alloc()(numsize);
    bnX = BN_new();
    bnY = BN_new();
    if (!buffer || !bnX || !bnY)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto _ec_to_string_cleanup;
    }
    if (1 != EC_POINT_get_affine_coordinates_GFp(params, pub, bnX, bnY, NULL))
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto _ec_to_string_cleanup;
    }

    // output the x coordinate
    offset = numsize - BN_num_bytes(bnX);
    memset(buffer, 0, numsize);
    BN_bn2bin(bnX, (buffer + offset));
    if (!cjose_base64url_encode(buffer, numsize, &b64u, &len, err))
    {
        goto _ec_to_string_cleanup;
    }
    field = json_stringn(b64u, len);
    if (!field)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto _ec_to_string_cleanup;
    }
    json_object_set(json, "x", field);
    json_decref(field);
    field = NULL;
    cjose_get_dealloc()(b64u);
    b64u = NULL;

    // output the y coordinate
    offset = numsize - BN_num_bytes(bnY);
    memset(buffer, 0, numsize);
    BN_bn2bin(bnY, (buffer + offset));
    if (!cjose_base64url_encode(buffer, numsize, &b64u, &len, err))
    {
        goto _ec_to_string_cleanup;
    }
    field = json_stringn(b64u, len);
    if (!field)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto _ec_to_string_cleanup;
    }
    json_object_set(json, "y", field);
    json_decref(field);
    field = NULL;
    cjose_get_dealloc()(b64u);
    b64u = NULL;

    result = true;

    _ec_to_string_cleanup:
    if (field)
    {
        json_decref(field);
    }
    if (bnX)
    {
        BN_free(bnX);
    }
    if (bnY)
    {
        BN_free(bnY);
    }
    if (buffer)
    {
        cjose_get_dealloc()(buffer);
    }
    if (b64u)
    {
        cjose_get_dealloc()(b64u);
    }

    return result;
}
Ejemplo n.º 30
0
cjose_jwk_t *cjose_jwk_create_EC_spec(
        const cjose_jwk_ec_keyspec *spec, cjose_err *err)
{
    cjose_jwk_t *   jwk = NULL;
    EC_KEY *        ec = NULL;
    EC_GROUP *      params = NULL;
    EC_POINT *      Q = NULL;
    BIGNUM *        bnD = NULL;
    BIGNUM *        bnX = NULL;
    BIGNUM *        bnY = NULL;

    if (!spec)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        return NULL;
    }

    bool            hasPriv = (NULL != spec->d && 0 < spec->dlen);
    bool            hasPub = ((NULL != spec->x && 0 < spec->xlen) &&
                             (NULL != spec->y && 0 < spec->ylen));
    if (!hasPriv && !hasPub)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        return NULL;
    }

    ec = EC_KEY_new_by_curve_name(spec->crv);
    if (NULL == ec)
    {
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
        goto create_EC_failed;
    }

    params = (EC_GROUP *)EC_KEY_get0_group(ec);
    if (NULL == params)
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto create_EC_failed;
    }

    // convert d from octet string to BIGNUM
    if (hasPriv)
    {
        bnD = BN_bin2bn(spec->d, spec->dlen, NULL);
        if (NULL == bnD)
        {
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
            goto create_EC_failed;
        }
        if (1 != EC_KEY_set_private_key(ec, bnD))
        {
            CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
            goto create_EC_failed;
        }

        // calculate public key from private
        Q = EC_POINT_new(params);
        if (NULL == Q)
        {
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
            goto create_EC_failed;
        }
        if (1 != EC_POINT_mul(params, Q, bnD, NULL, NULL, NULL))
        {
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
            goto create_EC_failed;
        }

        // public key is set below
        // ignore provided public key!
        hasPub = false;
    }
    if (hasPub)
    {
        Q = EC_POINT_new(params);
        if (NULL == Q)
        {
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
            goto create_EC_failed;
        }

        bnX = BN_bin2bn(spec->x, spec->xlen, NULL);
        bnY = BN_bin2bn(spec->y, spec->ylen, NULL);
        if (!bnX || !bnY)
        {
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
            goto create_EC_failed;
        }

        if (1 != EC_POINT_set_affine_coordinates_GFp(params, Q, bnX, bnY, NULL))
        {
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
            goto create_EC_failed;
        }
    }

    // always set the public key
    if (1 != EC_KEY_set_public_key(ec, Q))
    {
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
        goto create_EC_failed;
    }
    
    jwk = _EC_new(spec->crv, ec, err);
    if (!jwk)
    {
        goto create_EC_failed;
    }

    // jump to cleanup
    goto create_EC_cleanup;

    create_EC_failed:
    if (jwk)
    {
        cjose_get_dealloc()(jwk);
        jwk = NULL;
    }
    if (ec)
    {
        EC_KEY_free(ec);
        ec = NULL;
    }

    create_EC_cleanup:
    if (Q)
    {
        EC_POINT_free(Q);
        Q = NULL;
    }
    if (bnD)
    {
        BN_free(bnD);
        bnD = NULL;
    }
    if (bnX)
    {
        BN_free(bnX);
        bnX = NULL;
    }
    if (bnY)
    {
        BN_free(bnY);
        bnY = NULL;
    }

    return jwk;
}