<commit_before>/*
 * partial PKCS15 emulation for CAC-II cards
 * only minimal use of the authentication cert and key
 *
 * Copyright (C) 2005,2006,2007,2008,2009,2010
 *               <NAME> <<EMAIL>>
 *               2004, <NAME> <<EMAIL>>
 * Copyright (C) 2006, Identity Alliance,
 *               <NAME> <<EMAIL>>
 * Copyright (C) 2007, EMC, <NAME> <<EMAIL>>
 * Copyright (C) 2016, Red Hat, Inc.
 *
 * CAC driver author: <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>

#include "internal.h"
#include "cardctl.h"
#include "pkcs15.h"
/* X509 Key Usage flags */
#include "../pkcs15init/pkcs15-init.h"

/* probably should get manufacturer ID from cuid */
#define MANU_ID		"Common Access Card"

int sc_pkcs15emu_cac_init_ex(sc_pkcs15_card_t *, struct sc_aid *, sc_pkcs15emu_opt_t *);



typedef struct pdata_st {
	const char *id;
	const char *label;
	const char *path;
	int         ref;
	int         type;
	unsigned int maxlen;
	unsigned int minlen;
	unsigned int storedlen;
	int         flags;
	int         tries_left;
	const unsigned char  pad_char;
	int         obj_flags;
} pindata;

static int cac_detect_card(sc_pkcs15_card_t *p15card)
{
	sc_card_t *card = p15card->card;

	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
	if (card->type < SC_CARD_TYPE_CAC_GENERIC
		|| card->type >= SC_CARD_TYPE_CAC_GENERIC+1000)
		return SC_ERROR_INVALID_CARD;
	return SC_SUCCESS;
}

#define CAC_NUM_CERTS_AND_KEYS 10

static const char * cac_get_name(int type)
{
    switch (type) {
    case SC_CARD_TYPE_CAC_I: return ("CAC I");
    case SC_CARD_TYPE_CAC_II: return ("CAC II");
    default: break;
    }
    return ("CAC");
}

/*
 * These could move to a helper file for other cards that wish to use usage as a way of getting flags
 */

/* Only certain usages are valid for a given algorithm, return all the usages that the algorithm supports so we
 * can use it as a filter for all the public and private key usages */
static unsigned int
cac_alg_flags_from_algorithm(int algorithm)
{
	switch (algorithm) {
	case SC_ALGORITHM_RSA:
		return SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP |
		       SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
		       SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP |
		       SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
		       SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
	case SC_ALGORITHM_DSA:
		return SC_PKCS15_PRKEY_USAGE_VERIFY| SC_PKCS15_PRKEY_USAGE_SIGN |
		       SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
#ifdef SC_ALGORITHM_DH
	case SC_ALGORITHM_DH:
		return SC_PKCS15_PRKEY_USAGE_DERIVE ;
#endif
	case SC_ALGORITHM_EC:
		return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY|
		       SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
	case SC_ALGORITHM_GOSTR3410:
		return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY|
		       SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
	}
	return 0;
}


/* These are the cert key usage bits that map to various PKCS #11 (and thus PKCS #15) flags */
#define CAC_X509_USAGE_SIGNATURE		\
	(SC_PKCS15INIT_X509_DIGITAL_SIGNATURE	| \
	SC_PKCS15INIT_X509_NON_REPUDIATION	| \
	SC_PKCS15INIT_X509_KEY_CERT_SIGN 	| \
	SC_PKCS15INIT_X509_CRL_SIGN)
#define CAC_X509_USAGE_DERIVE			\
	SC_PKCS15INIT_X509_KEY_AGREEMENT
#define CAC_X509_USAGE_UNWRAP 			\
	(SC_PKCS15INIT_X509_KEY_ENCIPHERMENT	| \
	SC_PKCS15INIT_X509_KEY_AGREEMENT)
#define CAC_X509_USAGE_DECRYPT			\
	(SC_PKCS15INIT_X509_DATA_ENCIPHERMENT 	\
	/* | encipher? */)
#define CAC_X509_USAGE_NONREPUDIATION		\
	SC_PKCS15INIT_X509_NON_REPUDIATION

/* map a cert usage and algorithm to public and private key usages */
static int
cac_map_usage(unsigned long long cert_usage, int algorithm, unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, int allow_nonrepudiation)
{
	unsigned int pub_usage = 0, pr_usage = 0;
	unsigned int alg_flags = cac_alg_flags_from_algorithm(algorithm);

	if (cert_usage & CAC_X509_USAGE_SIGNATURE) {
		pub_usage |= SC_PKCS15_PRKEY_USAGE_VERIFY|SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER;
		pr_usage |= SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER;<commit_msg>Restore the functionality of CAC usage flags deriving from X509 certificates<commit_after>/*
 * partial PKCS15 emulation for CAC-II cards
 * only minimal use of the authentication cert and key
 *
 * Copyright (C) 2005,2006,2007,2008,2009,2010
 *               <NAME> <<EMAIL>>
 *               2004, <NAME> <<EMAIL>>
 * Copyright (C) 2006, Identity Alliance,
 *               <NAME> <<EMAIL>>
 * Copyright (C) 2007, EMC, <NAME> <<EMAIL>>
 * Copyright (C) 2016, Red Hat, Inc.
 *
 * CAC driver author: <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>

#include "internal.h"
#include "cardctl.h"
#include "pkcs15.h"
/* X509 Key Usage flags */
#include "../pkcs15init/pkcs15-init.h"

/* probably should get manufacturer ID from cuid */
#define MANU_ID		"Common Access Card"

int sc_pkcs15emu_cac_init_ex(sc_pkcs15_card_t *, struct sc_aid *, sc_pkcs15emu_opt_t *);



typedef struct pdata_st {
	const char *id;
	const char *label;
	const char *path;
	int         ref;
	int         type;
	unsigned int maxlen;
	unsigned int minlen;
	unsigned int storedlen;
	int         flags;
	int         tries_left;
	const unsigned char  pad_char;
	int         obj_flags;
} pindata;

static int cac_detect_card(sc_pkcs15_card_t *p15card)
{
	sc_card_t *card = p15card->card;

	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
	if (card->type < SC_CARD_TYPE_CAC_GENERIC
		|| card->type >= SC_CARD_TYPE_CAC_GENERIC+1000)
		return SC_ERROR_INVALID_CARD;
	return SC_SUCCESS;
}

#define CAC_NUM_CERTS_AND_KEYS 10

static const char * cac_get_name(int type)
{
    switch (type) {
    case SC_CARD_TYPE_CAC_I: return ("CAC I");
    case SC_CARD_TYPE_CAC_II: return ("CAC II");
    default: break;
    }
    return ("CAC");
}

/*
 * These could move to a helper file for other cards that wish to use usage as a way of getting flags
 */

/* Only certain usages are valid for a given algorithm, return all the usages that the algorithm supports so we
 * can use it as a filter for all the public and private key usages */
static unsigned int
cac_alg_flags_from_algorithm(int algorithm)
{
	switch (algorithm) {
	case SC_ALGORITHM_RSA:
		return SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP |
		       SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
		       SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP |
		       SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
		       SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
	case SC_ALGORITHM_DSA:
		return SC_PKCS15_PRKEY_USAGE_VERIFY| SC_PKCS15_PRKEY_USAGE_SIGN |
		       SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
#ifdef SC_ALGORITHM_DH
	case SC_ALGORITHM_DH:
		return SC_PKCS15_PRKEY_USAGE_DERIVE ;
#endif
	case SC_ALGORITHM_EC:
		return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY|
		       SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
	case SC_ALGORITHM_GOSTR3410:
		return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY|
		       SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
	}
	return 0;
}

#define SC_X509_DIGITAL_SIGNATURE     0x0001UL
#define SC_X509_NON_REPUDIATION       0x0002UL
#define SC_X509_KEY_ENCIPHERMENT      0x0004UL
#define SC_X509_DATA_ENCIPHERMENT     0x0008UL
#define SC_X509_KEY_AGREEMENT         0x0010UL
#define SC_X509_KEY_CERT_SIGN         0x0020UL
#define SC_X509_CRL_SIGN              0x0040UL
#define SC_X509_SIGN_ONLY             0x0080UL
#define SC_X509_DECIPHER_ONLY         0x0100UL

/* These are the cert key usage bits that map to various PKCS #11 (and thus PKCS #15) flags */
#define CAC_X509_USAGE_SIGNATURE \
	(SC_X509_DIGITAL_SIGNATURE | \
	SC_X509_NON_REPUDIATION    | \
	SC_X509_KEY_CERT_SIGN      | \
	SC_X509_CRL_SIGN)
#define CAC_X509_USAGE_DERIVE \
	SC_X509_KEY_AGREEMENT
#define CAC_X509_USAGE_UNWRAP \
	(SC_X509_KEY_ENCIPHERMENT | \
	SC_X509_KEY_AGREEMENT)
#define CAC_X509_USAGE_DECRYPT \
	(SC_X509_DATA_ENCIPHERMENT | \
	SC_X509_SIGN_ONLY)
#define CAC_X509_USAGE_NONREPUDIATION \
	SC_X509_NON_REPUDIATION

/* map a cert usage and algorithm to public and private key usages */
static int
cac_map_usage(unsigned long long cert_usage, int algorithm, unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, int allow_nonrepudiation)
{
	unsigned int pub_usage = 0, pr_usage = 0;
	unsigned int alg_flags = cac_alg_flags_from_algorithm(algorithm);

	if (cert_usage & CAC_X509_USAGE_SIGNATURE) {
		pub_usage |= SC_PKCS15_PRKEY_USAGE_VERIFY|SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER;
		pr_usage |= SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER;
{'fraction_non_alphanumeric': 0.07101505210343496, 'fraction_numerical': 0.04612118873021999, 'mean_word_length': 4.406885758998435, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3681781', 'n_tokens_mistral': 4290, 'n_tokens_neox': 3885, 'n_words': 974}