Example #1
0
static int verify_digest(unsigned char* input, unsigned char *digest, int hash_size)
{
	int ret = -1;
	X509_SIG *sig = NULL;
	uint32_t len = read_der_message_length(input);
	if(!len)
	{
		dprintf(CRITICAL, "boot_verifier: Signature length is invalid.\n");
		return ret;
	}

	sig = d2i_X509_SIG(NULL, &input, len);
	if(sig == NULL)
	{
		dprintf(CRITICAL, "boot_verifier: Reading digest failed\n");
		return ret;
	}

	if(sig->digest->length != SHA256_SIZE)
	{
		dprintf(CRITICAL, "boot_verifier: Digest length error.\n");
		goto verify_digest_error;
	}

	if(memcmp(sig->digest->data, digest, hash_size) == 0)
		ret = 0;

verify_digest_error:
	if(sig != NULL)
		X509_SIG_free(sig);

	return ret;
}
Example #2
0
EVP_PKEY *
PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u)
{
	char *nm = NULL;
	const unsigned char *p = NULL;
	unsigned char *data = NULL;
	long len;
	int slen;
	EVP_PKEY *ret = NULL;

	if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY,
	    bp, cb, u))
		return NULL;
	p = data;

	if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) {
		PKCS8_PRIV_KEY_INFO *p8inf;
		p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
		if (!p8inf)
			goto p8err;
		ret = EVP_PKCS82PKEY(p8inf);
		if (x) {
			EVP_PKEY_free(*x);
			*x = ret;
		}
		PKCS8_PRIV_KEY_INFO_free(p8inf);
	} else if (strcmp(nm, PEM_STRING_PKCS8) == 0) {
		PKCS8_PRIV_KEY_INFO *p8inf;
		X509_SIG *p8;
		int klen;
		char psbuf[PEM_BUFSIZE];
		p8 = d2i_X509_SIG(NULL, &p, len);
		if (!p8)
			goto p8err;
		if (cb)
			klen = cb(psbuf, PEM_BUFSIZE, 0, u);
		else
			klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
		if (klen <= 0) {
			PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY,
			    PEM_R_BAD_PASSWORD_READ);
			X509_SIG_free(p8);
			goto err;
		}
		p8inf = PKCS8_decrypt(p8, psbuf, klen);
		X509_SIG_free(p8);
		if (!p8inf)
			goto p8err;
		ret = EVP_PKCS82PKEY(p8inf);
		if (x) {
			EVP_PKEY_free(*x);
			*x = ret;
		}
		PKCS8_PRIV_KEY_INFO_free(p8inf);
	} else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0) {
		const EVP_PKEY_ASN1_METHOD *ameth;
		ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
		if (!ameth || !ameth->old_priv_decode)
			goto p8err;
		ret = d2i_PrivateKey(ameth->pkey_id, x, &p, len);
	}

p8err:
	if (ret == NULL)
		PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, ERR_R_ASN1_LIB);
err:
	free(nm);
	OPENSSL_cleanse(data, len);
	free(data);
	return (ret);
}
Example #3
0
EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u)
	{
	char *nm=NULL;
	const unsigned char *p=NULL;
	unsigned char *data=NULL;
	long len;
	EVP_PKEY *ret=NULL;

	if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u))
		return NULL;
	p = data;

	if (strcmp(nm,PEM_STRING_RSA) == 0)
		ret=d2i_PrivateKey(EVP_PKEY_RSA,x,&p,len);
	else if (strcmp(nm,PEM_STRING_DSA) == 0)
		ret=d2i_PrivateKey(EVP_PKEY_DSA,x,&p,len);
	else if (strcmp(nm,PEM_STRING_ECPRIVATEKEY) == 0)
		ret=d2i_PrivateKey(EVP_PKEY_EC,x,&p,len);
	else if (strcmp(nm,PEM_STRING_PKCS8INF) == 0) {
		PKCS8_PRIV_KEY_INFO *p8inf;
		p8inf=d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
		if(!p8inf) goto p8err;
		ret = EVP_PKCS82PKEY(p8inf);
		if(x) {
			if(*x) EVP_PKEY_free((EVP_PKEY *)*x);
			*x = ret;
		}
		PKCS8_PRIV_KEY_INFO_free(p8inf);
	} else if (strcmp(nm,PEM_STRING_PKCS8) == 0) {
		PKCS8_PRIV_KEY_INFO *p8inf;
		X509_SIG *p8;
		int klen;
		char psbuf[PEM_BUFSIZE];
		p8 = d2i_X509_SIG(NULL, &p, len);
		if(!p8) goto p8err;
		if (cb) klen=cb(psbuf,PEM_BUFSIZE,0,u);
		else klen=PEM_def_callback(psbuf,PEM_BUFSIZE,0,u);
		if (klen <= 0) {
			PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY,
					PEM_R_BAD_PASSWORD_READ);
			X509_SIG_free(p8);
			goto err;
		}
		p8inf = PKCS8_decrypt(p8, psbuf, klen);
		X509_SIG_free(p8);
		if(!p8inf) goto p8err;
		ret = EVP_PKCS82PKEY(p8inf);
		if(x) {
			if(*x) EVP_PKEY_free((EVP_PKEY *)*x);
			*x = ret;
		}
		PKCS8_PRIV_KEY_INFO_free(p8inf);
	}
p8err:
	if (ret == NULL)
		PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY,ERR_R_ASN1_LIB);
err:
	OPENSSL_free(nm);
	OPENSSL_cleanse(data, len);
	OPENSSL_free(data);
	return(ret);
	}
Example #4
0
/*
 * Encrypted PKCS#8 decoder.  It operates by just decrypting the given blob
 * into a new blob, which is returned as an EMBEDDED STORE_INFO.  The whole
 * decoding process will then start over with the new blob.
 */
static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name,
                                                  const char *pem_header,
                                                  const unsigned char *blob,
                                                  size_t len, void **pctx,
                                                  int *matchcount,
                                                  const UI_METHOD *ui_method,
                                                  void *ui_data)
{
    X509_SIG *p8 = NULL;
    char kbuf[PEM_BUFSIZE];
    char *pass = NULL;
    const X509_ALGOR *dalg = NULL;
    const ASN1_OCTET_STRING *doct = NULL;
    OSSL_STORE_INFO *store_info = NULL;
    BUF_MEM *mem = NULL;
    unsigned char *new_data = NULL;
    int new_data_len;

    if (pem_name != NULL) {
        if (strcmp(pem_name, PEM_STRING_PKCS8) != 0)
            return NULL;
        *matchcount = 1;
    }

    if ((p8 = d2i_X509_SIG(NULL, &blob, len)) == NULL)
        return NULL;

    *matchcount = 1;

    if ((mem = BUF_MEM_new()) == NULL) {
        OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED,
                      ERR_R_MALLOC_FAILURE);
        goto nop8;
    }

    if ((pass = file_get_pass(ui_method, kbuf, PEM_BUFSIZE,
                              "PKCS8 decrypt password", ui_data)) == NULL) {
        OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED,
                      OSSL_STORE_R_BAD_PASSWORD_READ);
        goto nop8;
    }

    X509_SIG_get0(p8, &dalg, &doct);
    if (!PKCS12_pbe_crypt(dalg, pass, strlen(pass), doct->data, doct->length,
                          &new_data, &new_data_len, 0))
        goto nop8;

    mem->data = (char *)new_data;
    mem->max = mem->length = (size_t)new_data_len;
    X509_SIG_free(p8);

    store_info = ossl_store_info_new_EMBEDDED(PEM_STRING_PKCS8INF, mem);
    if (store_info == NULL) {
        OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED,
                      ERR_R_MALLOC_FAILURE);
        goto nop8;
    }

    return store_info;
 nop8:
    X509_SIG_free(p8);
    BUF_MEM_free(mem);
    return NULL;
}
Example #5
0
int ccn_verify_signature(const unsigned char *msg,
                     size_t size,
                     const struct ccn_parsed_ContentObject *co,
                     const struct ccn_pkey *verification_pubkey)
{
    EVP_MD_CTX verc;
    EVP_MD_CTX *ver_ctx = &verc;
    X509_SIG *digest_info = NULL;
    MP_info *merkle_path_info = NULL;
    unsigned char *root_hash;
    size_t root_hash_size;

    int res;

    const EVP_MD *digest = EVP_md_null();
    const EVP_MD *merkle_path_digest = EVP_md_null();

    const unsigned char *signature_bits = NULL;
    size_t signature_bits_size = 0;
    const unsigned char *witness = NULL;
    size_t witness_size = 0;
    EVP_PKEY *pkey = (EVP_PKEY *)verification_pubkey;
#ifdef DEBUG
    int x, h;
#endif

    res = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, msg,
                              co->offset[CCN_PCO_B_SignatureBits],
                              co->offset[CCN_PCO_E_SignatureBits],
                              &signature_bits,
                              &signature_bits_size);
    if (res < 0)
        return (-1);

    if (co->offset[CCN_PCO_B_DigestAlgorithm] == co->offset[CCN_PCO_E_DigestAlgorithm]) {
        digest = EVP_sha256();
    }
    else {
        /* XXX - figure out what algorithm the OID represents */
        fprintf(stderr, "not a DigestAlgorithm I understand right now\n");
        return (-1);
    }

    EVP_MD_CTX_init(ver_ctx);
    res = EVP_VerifyInit_ex(ver_ctx, digest, NULL);
    if (!res)
        return (-1);

    if (co->offset[CCN_PCO_B_Witness] != co->offset[CCN_PCO_E_Witness]) {
        /* The witness is a DigestInfo, where the octet-string therein encapsulates
         * a sequence of [integer (origin 1 node#), sequence of [octet-string]]
         * where the inner octet-string is the concatenated hashes on the merkle-path
         */
        res = ccn_ref_tagged_BLOB(CCN_DTAG_Witness, msg,
                                  co->offset[CCN_PCO_B_Witness],
                                  co->offset[CCN_PCO_E_Witness],
                                  &witness,
                                  &witness_size);
        if (res < 0)
            return (-1);


        digest_info = d2i_X509_SIG(NULL, &witness, witness_size);
        /* digest_info->algor->algorithm->{length, data}
         * digest_info->digest->{length, type, data}
         */
        /* ...2.2 is an MHT w/ SHA256 */
        ASN1_OBJECT *merkle_hash_tree_oid = OBJ_txt2obj("1.2.840.113550.11.1.2.2", 1);
        if (0 != OBJ_cmp(digest_info->algor->algorithm, merkle_hash_tree_oid)) {
            fprintf(stderr, "A witness is present without an MHT OID!\n");
            ASN1_OBJECT_free(merkle_hash_tree_oid);
            return (-1);
        }
        /* we're doing an MHT */
        ASN1_OBJECT_free(merkle_hash_tree_oid);
        merkle_path_digest = EVP_sha256();
        /* DER-encoded in the digest_info's digest ASN.1 octet string is the Merkle path info */
        merkle_path_info = d2i_MP_info(NULL, (const unsigned char **)&(digest_info->digest->data), digest_info->digest->length);
#ifdef DEBUG
        int node = ASN1_INTEGER_get(merkle_path_info->node);
        int hash_count = merkle_path_info->hashes->num;
        ASN1_OCTET_STRING *hash;
        fprintf(stderr, "A witness is present with an MHT OID\n");
        fprintf(stderr, "This is node %d, with %d hashes\n", node, hash_count);
        for (h = 0; h < hash_count; h++) {
            hash = (ASN1_OCTET_STRING *)merkle_path_info->hashes->data[h];
            fprintf(stderr, "     hashes[%d] len = %d data = ", h, hash->length);
            for (x = 0; x < hash->length; x++) {
                fprintf(stderr, "%02x", hash->data[x]);
            }
            fprintf(stderr, "\n");
        }
#endif
        /* In the MHT signature case, we signed/verify the root hash */
        root_hash_size = EVP_MD_size(merkle_path_digest);
        root_hash = calloc(1, root_hash_size);
        res = ccn_merkle_root_hash(msg, size, co, merkle_path_digest, merkle_path_info, root_hash, root_hash_size);
        res = EVP_VerifyUpdate(ver_ctx, root_hash, root_hash_size);
        res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey);
        EVP_MD_CTX_cleanup(ver_ctx);
    } else {
        /*
         * In the simple signature case, we signed/verify from the name through
         * the end of the content.
         */
        size_t signed_size = co->offset[CCN_PCO_E_Content] - co->offset[CCN_PCO_B_Name];
        res = EVP_VerifyUpdate(ver_ctx, msg + co->offset[CCN_PCO_B_Name], signed_size);
        res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey);
        EVP_MD_CTX_cleanup(ver_ctx);
    }

    if (res == 1)
        return (1);
    else
        return (0);
}
Example #6
0
int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
	     unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
	{
	int i,ret=0,sigtype;
	unsigned char *p,*s;
	X509_SIG *sig=NULL;

	if (siglen != (unsigned int)RSA_size(rsa))
		{
		RSAerr(RSA_F_RSA_VERIFY,RSA_R_WRONG_SIGNATURE_LENGTH);
		return(0);
		}

	if((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify)
		{
		return rsa->meth->rsa_verify(dtype, m, m_len,
			sigbuf, siglen, rsa);
		}

	s=(unsigned char *)OPENSSL_malloc((unsigned int)siglen);
	if (s == NULL)
		{
		RSAerr(RSA_F_RSA_VERIFY,ERR_R_MALLOC_FAILURE);
		goto err;
		}
	if((dtype == NID_md5_sha1) && (m_len != SSL_SIG_LENGTH) ) {
			RSAerr(RSA_F_RSA_VERIFY,RSA_R_INVALID_MESSAGE_LENGTH);
			goto err;
	}
	i=RSA_public_decrypt((int)siglen,sigbuf,s,rsa,RSA_PKCS1_PADDING);

	if (i <= 0) goto err;

	/* Special case: SSL signature */
	if(dtype == NID_md5_sha1) {
		if((i != SSL_SIG_LENGTH) || memcmp(s, m, SSL_SIG_LENGTH))
				RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
		else ret = 1;
	} else {
		p=s;
		sig=d2i_X509_SIG(NULL,&p,(long)i);

		if (sig == NULL) goto err;

		/* Excess data can be used to create forgeries */
		if(p != s+i)
			{
			RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
			goto err;
			}

		/* Parameters to the signature algorithm can also be used to
		   create forgeries */
		if(sig->algor->parameter
		   && ASN1_TYPE_get(sig->algor->parameter) != V_ASN1_NULL)
			{
			RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
			goto err;
			}

		sigtype=OBJ_obj2nid(sig->algor->algorithm);


	#ifdef RSA_DEBUG
		/* put a backward compatibility flag in EAY */
		fprintf(stderr,"in(%s) expect(%s)\n",OBJ_nid2ln(sigtype),
			OBJ_nid2ln(dtype));
	#endif
		if (sigtype != dtype)
			{
			if (((dtype == NID_md5) &&
				(sigtype == NID_md5WithRSAEncryption)) ||
				((dtype == NID_md2) &&
				(sigtype == NID_md2WithRSAEncryption)))
				{
				/* ok, we will let it through */
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16)
				fprintf(stderr,"signature has problems, re-make with post SSLeay045\n");
#endif
				}
			else
				{
				RSAerr(RSA_F_RSA_VERIFY,
						RSA_R_ALGORITHM_MISMATCH);
				goto err;
				}
			}
		if (	((unsigned int)sig->digest->length != m_len) ||
			(memcmp(m,sig->digest->data,m_len) != 0))
			{
			RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
			}
		else
			ret=1;
	}
err:
	if (sig != NULL) X509_SIG_free(sig);
	if (s != NULL)
		{
		OPENSSL_cleanse(s,(unsigned int)siglen);
		OPENSSL_free(s);
		}
	return(ret);
	}
Example #7
0
int int_rsa_verify(int dtype, const unsigned char *m,
                   unsigned int m_len,
                   unsigned char *rm, size_t *prm_len,
                   const unsigned char *sigbuf, size_t siglen, RSA *rsa)
{
    int i, ret = 0, sigtype;
    unsigned char *s;
    X509_SIG *sig = NULL;

    if (siglen != (unsigned int)RSA_size(rsa)) {
        RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_WRONG_SIGNATURE_LENGTH);
        return (0);
    }

    if ((dtype == NID_md5_sha1) && rm) {
        i = RSA_public_decrypt((int)siglen,
                               sigbuf, rm, rsa, RSA_PKCS1_PADDING);
        if (i <= 0)
            return 0;
        *prm_len = i;
        return 1;
    }

    s = OPENSSL_malloc((unsigned int)siglen);
    if (s == NULL) {
        RSAerr(RSA_F_INT_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if ((dtype == NID_md5_sha1) && (m_len != SSL_SIG_LENGTH)) {
        RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_MESSAGE_LENGTH);
        goto err;
    }
    i = RSA_public_decrypt((int)siglen, sigbuf, s, rsa, RSA_PKCS1_PADDING);

    if (i <= 0)
        goto err;
    /*
     * Oddball MDC2 case: signature can be OCTET STRING. check for correct
     * tag and length octets.
     */
    if (dtype == NID_mdc2 && i == 18 && s[0] == 0x04 && s[1] == 0x10) {
        if (rm) {
            memcpy(rm, s + 2, 16);
            *prm_len = 16;
            ret = 1;
        } else if (memcmp(m, s + 2, 16))
            RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
        else
            ret = 1;
    }

    /* Special case: SSL signature */
    if (dtype == NID_md5_sha1) {
        if ((i != SSL_SIG_LENGTH) || memcmp(s, m, SSL_SIG_LENGTH))
            RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
        else
            ret = 1;
    } else {
        const unsigned char *p = s;
        sig = d2i_X509_SIG(NULL, &p, (long)i);

        if (sig == NULL)
            goto err;

        /* Excess data can be used to create forgeries */
        if (p != s + i || !rsa_check_digestinfo(sig, s, i)) {
            RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
            goto err;
        }

        /*
         * Parameters to the signature algorithm can also be used to create
         * forgeries
         */
        if (sig->algor->parameter
            && ASN1_TYPE_get(sig->algor->parameter) != V_ASN1_NULL) {
            RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
            goto err;
        }

        sigtype = OBJ_obj2nid(sig->algor->algorithm);

#ifdef RSA_DEBUG
        /* put a backward compatibility flag in EAY */
        fprintf(stderr, "in(%s) expect(%s)\n", OBJ_nid2ln(sigtype),
                OBJ_nid2ln(dtype));
#endif
        if (sigtype != dtype) {
            RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_ALGORITHM_MISMATCH);
            goto err;
        }
        if (rm) {
            const EVP_MD *md;
            md = EVP_get_digestbynid(dtype);
            if (md && (EVP_MD_size(md) != sig->digest->length))
                RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_DIGEST_LENGTH);
            else {
                memcpy(rm, sig->digest->data, sig->digest->length);
                *prm_len = sig->digest->length;
                ret = 1;
            }
        } else if (((unsigned int)sig->digest->length != m_len) ||
                   (memcmp(m, sig->digest->data, m_len) != 0)) {
            RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
        } else
            ret = 1;
    }
 err:
    X509_SIG_free(sig);
    OPENSSL_clear_free(s, (unsigned int)siglen);
    return (ret);
}
Example #8
0
EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
                                  void *u)
{
    char *nm = NULL;
    const unsigned char *p = NULL;
    unsigned char *data = NULL;
    long len;
    EVP_PKEY *ret = NULL;

    if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u))
        return NULL;
    p = data;

    if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) {
        PKCS8_PRIV_KEY_INFO *p8inf;
        p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
        if (!p8inf)
            goto p8err;
        ret = EVP_PKCS82PKEY(p8inf);
        if (x) {
            if (*x)
                EVP_PKEY_free((EVP_PKEY *)*x);
            *x = ret;
        }
        PKCS8_PRIV_KEY_INFO_free(p8inf);
    } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) {
        PKCS8_PRIV_KEY_INFO *p8inf;
        X509_SIG *p8;
        int klen;
        char psbuf[PEM_BUFSIZE];
        p8 = d2i_X509_SIG(NULL, &p, len);
        if (!p8)
            goto p8err;

        klen = 0;
        if (!cb)
            cb = PEM_def_callback;
        klen = cb(psbuf, PEM_BUFSIZE, 0, u);
        if (klen <= 0) {
            OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
            X509_SIG_free(p8);
            goto err;
        }
        p8inf = PKCS8_decrypt(p8, psbuf, klen);
        X509_SIG_free(p8);
        OPENSSL_cleanse(psbuf, klen);
        if (!p8inf)
            goto p8err;
        ret = EVP_PKCS82PKEY(p8inf);
        if (x) {
            if (*x)
                EVP_PKEY_free((EVP_PKEY *)*x);
            *x = ret;
        }
        PKCS8_PRIV_KEY_INFO_free(p8inf);
    } else if (strcmp(nm, PEM_STRING_RSA) == 0) {
        /* TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the
         * standalone format. This and the cases below probably should not
         * accept PKCS#8. */
        ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len);
    } else if (strcmp(nm, PEM_STRING_EC) == 0) {
        ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len);
    } else if (strcmp(nm, PEM_STRING_DSA) == 0) {
        ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len);
    }
 p8err:
    if (ret == NULL)
        OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);

 err:
    OPENSSL_free(nm);
    OPENSSL_cleanse(data, len);
    OPENSSL_free(data);
    return (ret);
}
Example #9
0
/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a
 * PKCS#12 structure. */
static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
                                      struct pkcs12_context *ctx) {
  CBS content_type, wrapped_contents, contents, content_infos;
  int nid, ret = 0;

  if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) ||
      !CBS_get_asn1(content_info, &wrapped_contents,
                        CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
    OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
    goto err;
  }

  nid = OBJ_cbs2nid(&content_type);
  if (nid == NID_pkcs7_encrypted) {
    /* See https://tools.ietf.org/html/rfc2315#section-13.
     *
     * PKCS#7 encrypted data inside a PKCS#12 structure is generally an
     * encrypted certificate bag and it's generally encrypted with 40-bit
     * RC2-CBC. */
    CBS version_bytes, eci, contents_type, ai, encrypted_contents;
    X509_ALGOR *algor = NULL;
    const uint8_t *inp;
    uint8_t *out;
    size_t out_len;

    if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) ||
        !CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) ||
        /* EncryptedContentInfo, see
         * https://tools.ietf.org/html/rfc2315#section-10.1 */
        !CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) ||
        !CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) ||
        /* AlgorithmIdentifier, see
         * https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */
        !CBS_get_asn1_element(&eci, &ai, CBS_ASN1_SEQUENCE) ||
        !CBS_get_asn1(&eci, &encrypted_contents,
                      CBS_ASN1_CONTEXT_SPECIFIC | 0)) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }

    if (OBJ_cbs2nid(&contents_type) != NID_pkcs7_data) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }

    inp = CBS_data(&ai);
    algor = d2i_X509_ALGOR(NULL, &inp, CBS_len(&ai));
    if (algor == NULL) {
      goto err;
    }
    if (inp != CBS_data(&ai) + CBS_len(&ai)) {
      X509_ALGOR_free(algor);
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }

    if (!pbe_crypt(algor, ctx->password, ctx->password_len,
                   CBS_data(&encrypted_contents), CBS_len(&encrypted_contents),
                   &out, &out_len, 0 /* decrypt */)) {
      X509_ALGOR_free(algor);
      goto err;
    }
    X509_ALGOR_free(algor);

    CBS_init(&content_infos, out, out_len);
    ret = PKCS12_handle_content_infos(&content_infos, depth + 1, ctx);
    OPENSSL_free(out);
  } else if (nid == NID_pkcs7_data) {
    CBS octet_string_contents;

    if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents,
                          CBS_ASN1_OCTETSTRING)) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }

    ret = PKCS12_handle_content_infos(&octet_string_contents, depth + 1, ctx);
  } else if (nid == NID_pkcs8ShroudedKeyBag) {
    /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
     * 4.2.2. */
    const uint8_t *inp = CBS_data(&wrapped_contents);
    PKCS8_PRIV_KEY_INFO *pki = NULL;
    X509_SIG *encrypted = NULL;

    if (*ctx->out_key) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12);
      goto err;
    }

    /* encrypted isn't actually an X.509 signature, but it has the same
     * structure as one and so |X509_SIG| is reused to store it. */
    encrypted = d2i_X509_SIG(NULL, &inp, CBS_len(&wrapped_contents));
    if (encrypted == NULL) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }
    if (inp != CBS_data(&wrapped_contents) + CBS_len(&wrapped_contents)) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      X509_SIG_free(encrypted);
      goto err;
    }

    pki = PKCS8_decrypt_pbe(encrypted, ctx->password, ctx->password_len);
    X509_SIG_free(encrypted);
    if (pki == NULL) {
      goto err;
    }

    *ctx->out_key = EVP_PKCS82PKEY(pki);
    PKCS8_PRIV_KEY_INFO_free(pki);

    if (ctx->out_key == NULL) {
      goto err;
    }
    ret = 1;
  } else if (nid == NID_certBag) {
    CBS cert_bag, cert_type, wrapped_cert, cert;

    if (!CBS_get_asn1(&wrapped_contents, &cert_bag, CBS_ASN1_SEQUENCE) ||
        !CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) ||
        !CBS_get_asn1(&cert_bag, &wrapped_cert,
                      CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
        !CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }

    if (OBJ_cbs2nid(&cert_type) == NID_x509Certificate) {
      const uint8_t *inp = CBS_data(&cert);
      X509 *x509 = d2i_X509(NULL, &inp, CBS_len(&cert));
      if (!x509) {
        OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                          PKCS8_R_BAD_PKCS12_DATA);
        goto err;
      }
      if (inp != CBS_data(&cert) + CBS_len(&cert)) {
        OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                          PKCS8_R_BAD_PKCS12_DATA);
        X509_free(x509);
        goto err;
      }

      if (0 == sk_X509_push(ctx->out_certs, x509)) {
        X509_free(x509);
        goto err;
      }
    }
    ret = 1;
  } else {
    /* Unknown element type - ignore it. */
    ret = 1;
  }

err:
  return ret;
}
int int_rsa_verify(int dtype, const unsigned char *m,
			  unsigned int m_len,
			  unsigned char *rm, size_t *prm_len,
			  const unsigned char *sigbuf, size_t siglen,
			  RSA *rsa)
	{
	int i,ret=0,sigtype;
	unsigned char *s;
	X509_SIG *sig=NULL;

	if (siglen != (unsigned int)RSA_size(rsa))
		{
		RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_WRONG_SIGNATURE_LENGTH);
		return(0);
		}

	if((dtype == NID_md5_sha1) && rm)
		{
		i = RSA_public_decrypt((int)siglen,
					sigbuf,rm,rsa,RSA_PKCS1_PADDING);
		if (i <= 0)
			return 0;
		*prm_len = i;
		return 1;
		}

	s=(unsigned char *)OPENSSL_malloc((unsigned int)siglen);
	if (s == NULL)
		{
		RSAerr(RSA_F_INT_RSA_VERIFY,ERR_R_MALLOC_FAILURE);
		goto err;
		}
	if((dtype == NID_md5_sha1) && (m_len != SSL_SIG_LENGTH) ) {
			RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_INVALID_MESSAGE_LENGTH);
			goto err;
	}
	i=RSA_public_decrypt((int)siglen,sigbuf,s,rsa,RSA_PKCS1_PADDING);

	if (i <= 0) goto err;

	/* Special case: SSL signature */
	if(dtype == NID_md5_sha1) {
		if((i != SSL_SIG_LENGTH) || TINYCLR_SSL_MEMCMP(s, m, SSL_SIG_LENGTH))
				RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
		else ret = 1;
	} else {
		const unsigned char *p=s;
		sig=d2i_X509_SIG(NULL,&p,(long)i);

		if (sig == NULL) goto err;

		/* Excess data can be used to create forgeries */
		if(p != s+i)
			{
			RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
			goto err;
			}

		/* Parameters to the signature algorithm can also be used to
		   create forgeries */
		if(sig->algor->parameter
		   && ASN1_TYPE_get(sig->algor->parameter) != V_ASN1_NULL)
			{
			RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
			goto err;
			}

		sigtype=OBJ_obj2nid(sig->algor->algorithm);


	#ifdef RSA_DEBUG
		/* put a backward compatibility flag in EAY */
		TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR,"in(%s) expect(%s)\n",OBJ_nid2ln(sigtype),
			OBJ_nid2ln(dtype));
	#endif
		if (sigtype != dtype)
			{
			if (((dtype == NID_md5) &&
				(sigtype == NID_md5WithRSAEncryption)) ||
				((dtype == NID_md2) &&
				(sigtype == NID_md2WithRSAEncryption)))
				{
				/* ok, we will let it through */
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16)
				TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR,"signature has problems, re-make with post SSLeay045\n");
#endif
				}
			else
				{
				RSAerr(RSA_F_INT_RSA_VERIFY,
						RSA_R_ALGORITHM_MISMATCH);
				goto err;
				}
			}
		if (rm)
			{
			const EVP_MD *md;
			md = EVP_get_digestbynid(dtype);
			if (md && (EVP_MD_size(md) != sig->digest->length))
				RSAerr(RSA_F_INT_RSA_VERIFY,
						RSA_R_INVALID_DIGEST_LENGTH);
			else
				{
				TINYCLR_SSL_MEMCPY(rm, sig->digest->data,
							sig->digest->length);
				*prm_len = sig->digest->length;
				ret = 1;
				}
			}
		else if (((unsigned int)sig->digest->length != m_len) ||
			(TINYCLR_SSL_MEMCMP(m,sig->digest->data,m_len) != 0))
			{
			RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
			}
		else
			ret=1;
	}
err:
	if (sig != NULL) X509_SIG_free(sig);
	if (s != NULL)
		{
		OPENSSL_cleanse(s,(unsigned int)siglen);
		OPENSSL_free(s);
		}
	return(ret);
	}
Example #11
0
int
int_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len,
    unsigned char *rm, size_t *prm_len, const unsigned char *sigbuf,
    size_t siglen, RSA *rsa)
{
	int i, ret = 0, sigtype;
	unsigned char *s;
	X509_SIG *sig = NULL;

	if (siglen != (unsigned int)RSA_size(rsa)) {
		RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_WRONG_SIGNATURE_LENGTH);
		return 0;
	}

	if ((dtype == NID_md5_sha1) && rm) {
		i = RSA_public_decrypt((int)siglen, sigbuf, rm, rsa,
		    RSA_PKCS1_PADDING);
		if (i <= 0)
			return 0;
		*prm_len = i;
		return 1;
	}

	s = malloc(siglen);
	if (s == NULL) {
		RSAerr(RSA_F_INT_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
		goto err;
	}
	if (dtype == NID_md5_sha1 && m_len != SSL_SIG_LENGTH) {
		RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_MESSAGE_LENGTH);
		goto err;
	}
	i = RSA_public_decrypt((int)siglen, sigbuf, s, rsa, RSA_PKCS1_PADDING);

	if (i <= 0)
		goto err;

	/* Special case: SSL signature */
	if (dtype == NID_md5_sha1) {
		if (i != SSL_SIG_LENGTH || memcmp(s, m, SSL_SIG_LENGTH))
			RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
		else
			ret = 1;
	} else {
		const unsigned char *p = s;

		sig = d2i_X509_SIG(NULL, &p, (long)i);

		if (sig == NULL)
			goto err;

		/* Excess data can be used to create forgeries */
		if (p != s + i) {
			RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
			goto err;
		}

		/* Parameters to the signature algorithm can also be used to
		   create forgeries */
		if (sig->algor->parameter &&
		    ASN1_TYPE_get(sig->algor->parameter) != V_ASN1_NULL) {
			RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
			goto err;
		}

		sigtype = OBJ_obj2nid(sig->algor->algorithm);

		if (sigtype != dtype) {
			RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_ALGORITHM_MISMATCH);
			goto err;
		}
		if (rm) {
			const EVP_MD *md;

			md = EVP_get_digestbynid(dtype);
			if (md && (EVP_MD_size(md) != sig->digest->length))
				RSAerr(RSA_F_INT_RSA_VERIFY,
				    RSA_R_INVALID_DIGEST_LENGTH);
			else {
				memcpy(rm, sig->digest->data,
				    sig->digest->length);
				*prm_len = sig->digest->length;
				ret = 1;
			}
		} else if ((unsigned int)sig->digest->length != m_len ||
		    memcmp(m, sig->digest->data, m_len) != 0) {
			RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
		} else
			ret = 1;
	}
err:
	if (sig != NULL)
		X509_SIG_free(sig);
	if (s != NULL) {
		explicit_bzero(s, (unsigned int)siglen);
		free(s);
	}
	return ret;
}
Example #12
0
int ndn_verify_signature(const unsigned char *msg,
                     size_t size,
                     const struct ndn_parsed_ContentObject *co,
                     const struct ndn_pkey *verification_pubkey)
{
    EVP_MD_CTX verc;
    EVP_MD_CTX *ver_ctx = &verc;
    X509_SIG *digest_info = NULL;
    const unsigned char *dd = NULL;
    MP_info *merkle_path_info = NULL;
    unsigned char *root_hash = NULL;
    size_t root_hash_size;

    int res;

    const EVP_MD *digest = NULL;
    const EVP_MD *merkle_path_digest = NULL;
    
    const unsigned char *signature_bits = NULL;
    size_t signature_bits_size = 0;
    const unsigned char *witness = NULL;
    size_t witness_size = 0;
    const unsigned char *digest_algorithm = NULL;
    size_t digest_algorithm_size;
    
    EVP_PKEY *pkey = (EVP_PKEY *)verification_pubkey;

    res = ndn_ref_tagged_BLOB(NDN_DTAG_SignatureBits, msg,
                              co->offset[NDN_PCO_B_SignatureBits],
                              co->offset[NDN_PCO_E_SignatureBits],
                              &signature_bits,
                              &signature_bits_size);
    if (res < 0)
        return (-1);

    if (co->offset[NDN_PCO_B_DigestAlgorithm] == co->offset[NDN_PCO_E_DigestAlgorithm]) {
        digest_algorithm = (const unsigned char *)NDN_SIGNING_DEFAULT_DIGEST_ALGORITHM;
    }
    else {
        /* figure out what algorithm the OID represents */
        res = ndn_ref_tagged_string(NDN_DTAG_DigestAlgorithm, msg,
                                  co->offset[NDN_PCO_B_DigestAlgorithm],
                                  co->offset[NDN_PCO_E_DigestAlgorithm],
                                  &digest_algorithm,
                                  &digest_algorithm_size);
        if (res < 0)
            return (-1);
        /* NOTE: since the element closer is a 0, and the element is well formed,
         * the string will be null terminated 
         */
    }
    digest = md_from_digest_and_pkey((const char *)digest_algorithm, verification_pubkey);
    EVP_MD_CTX_init(ver_ctx);
    res = EVP_VerifyInit_ex(ver_ctx, digest, NULL);
    if (!res) {
        EVP_MD_CTX_cleanup(ver_ctx);
        return (-1);
    }
    if (co->offset[NDN_PCO_B_Witness] != co->offset[NDN_PCO_E_Witness]) {
        /* The witness is a DigestInfo, where the octet-string therein encapsulates
         * a sequence of [integer (origin 1 node#), sequence of [octet-string]]
         * where the inner octet-string is the concatenated hashes on the merkle-path
         */
        res = ndn_ref_tagged_BLOB(NDN_DTAG_Witness, msg,
                                  co->offset[NDN_PCO_B_Witness],
                                  co->offset[NDN_PCO_E_Witness],
                                  &witness,
                                  &witness_size);
        if (res < 0) {
            EVP_MD_CTX_cleanup(ver_ctx);
            return (-1);
        }

        digest_info = d2i_X509_SIG(NULL, &witness, witness_size);
        /* digest_info->algor->algorithm->{length, data}
         * digest_info->digest->{length, type, data}
         */
        /* ...2.2 is an MHT w/ SHA256 */
        ASN1_OBJECT *merkle_hash_tree_oid = OBJ_txt2obj("1.2.840.113550.11.1.2.2", 1);
        if (0 != OBJ_cmp(digest_info->algor->algorithm, merkle_hash_tree_oid)) {
            fprintf(stderr, "A witness is present without an MHT OID!\n");
            EVP_MD_CTX_cleanup(ver_ctx);
            ASN1_OBJECT_free(merkle_hash_tree_oid);
            return (-1);
        }
        /* we're doing an MHT */
        ASN1_OBJECT_free(merkle_hash_tree_oid);
        merkle_path_digest = EVP_sha256();
        /* DER-encoded in the digest_info's digest ASN.1 octet string is the Merkle path info */
        dd = digest_info->digest->data;
        merkle_path_info = d2i_MP_info(NULL, &dd, digest_info->digest->length);
        X509_SIG_free(digest_info);
#ifdef DEBUG
        int x,h;
        int node = ASN1_INTEGER_get(merkle_path_info->node);
        int hash_count = sk_ASN1_OCTET_STRING_num(merkle_path_info->hashes);
        ASN1_OCTET_STRING *hash;
        fprintf(stderr, "A witness is present with an MHT OID\n");
        fprintf(stderr, "This is node %d, with %d hashes\n", node, hash_count);
        for (h = 0; h < hash_count; h++) {
            hash = sk_ASN1_OCTET_STRING_value(merkle_path_info->hashes, h);
            fprintf(stderr, "     hashes[%d] len = %d data = ", h, hash->length);
            for (x = 0; x < hash->length; x++) {
                fprintf(stderr, "%02x", hash->data[x]);
            }
            fprintf(stderr, "\n");
        }
#endif
        /* In the MHT signature case, we signed/verify the root hash */
        root_hash_size = EVP_MD_size(merkle_path_digest);
        root_hash = calloc(1, root_hash_size);
        res = ndn_merkle_root_hash(msg, size, co, merkle_path_digest, merkle_path_info, root_hash, root_hash_size);
        MP_info_free(merkle_path_info);
        if (res < 0) {
            EVP_MD_CTX_cleanup(ver_ctx);
            free(root_hash);
            return(-1);
        }
        res = EVP_VerifyUpdate(ver_ctx, root_hash, root_hash_size);
        free(root_hash);
        if (res == 0) {
            EVP_MD_CTX_cleanup(ver_ctx);
            return(-1);
        }
        res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey);
        EVP_MD_CTX_cleanup(ver_ctx);
    } else {
        /*
         * In the simple signature case, we signed/verify from the name through
         * the end of the content.
         */
        size_t signed_size = co->offset[NDN_PCO_E_Content] - co->offset[NDN_PCO_B_Name];
        res = EVP_VerifyUpdate(ver_ctx, msg + co->offset[NDN_PCO_B_Name], signed_size);
        if (res == 0) {
            EVP_MD_CTX_cleanup(ver_ctx);
            return(-1);
        }
        res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey);
        EVP_MD_CTX_cleanup(ver_ctx);
    }
    return (res);
}