195 lines
5.9 KiB
C
195 lines
5.9 KiB
C
/*
|
|
* card-openpgp.h: Support for OpenPGP card
|
|
*
|
|
* Copyright (C) 2020 Peter Marschall <peter@adpm.de>
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#ifndef _CARD_OPENPGP_H
|
|
#define _CARD_OPENPGP_H
|
|
|
|
/*
|
|
* The OpenPGP card doesn't have a file system, instead everything
|
|
* is stored in data objects that are accessed through GET/PUT.
|
|
*
|
|
* However, much inside OpenSC's pkcs15 implementation is based on
|
|
* the assumption that we have a file system. So we fake one here.
|
|
*
|
|
* Selecting the MF causes us to select the OpenPGP AID.
|
|
*
|
|
* Everything else is mapped to "file" IDs.
|
|
*/
|
|
|
|
typedef enum _pgp_do_type { /* DO type */
|
|
SIMPLE = SC_FILE_TYPE_WORKING_EF,
|
|
CONSTRUCTED = SC_FILE_TYPE_DF
|
|
} pgp_do_type_t;
|
|
|
|
typedef enum _pgp_version { /* 2-byte BCD-alike encoded version number */
|
|
OPENPGP_CARD_1_0 = 0x0100,
|
|
OPENPGP_CARD_1_1 = 0x0101,
|
|
OPENPGP_CARD_2_0 = 0x0200,
|
|
OPENPGP_CARD_2_1 = 0x0201,
|
|
OPENPGP_CARD_2_2 = 0x0202,
|
|
OPENPGP_CARD_3_0 = 0x0300,
|
|
OPENPGP_CARD_3_1 = 0x0301,
|
|
OPENPGP_CARD_3_2 = 0x0302,
|
|
OPENPGP_CARD_3_3 = 0x0303,
|
|
OPENPGP_CARD_3_4 = 0x0304,
|
|
} pgp_version_t;
|
|
|
|
typedef enum _pgp_access { /* access flags for the respective DO/file */
|
|
READ_NEVER = 0x0010,
|
|
READ_PIN1 = 0x0011,
|
|
READ_PIN2 = 0x0012,
|
|
READ_PIN3 = 0x0014,
|
|
READ_ALWAYS = 0x0018,
|
|
READ_MASK = 0x00FF,
|
|
WRITE_NEVER = 0x1000,
|
|
WRITE_PIN1 = 0x1100,
|
|
WRITE_PIN2 = 0x1200,
|
|
WRITE_PIN3 = 0x1400,
|
|
WRITE_ALWAYS = 0x1800,
|
|
WRITE_MASK = 0x1F00
|
|
} pgp_access_t;
|
|
|
|
typedef enum _pgp_ext_caps { /* extended capabilities/features: bit flags */
|
|
EXT_CAP_ALG_ATTR_CHANGEABLE = 0x0004,
|
|
EXT_CAP_PRIVATE_DO = 0x0008,
|
|
EXT_CAP_C4_CHANGEABLE = 0x0010,
|
|
EXT_CAP_KEY_IMPORT = 0x0020,
|
|
EXT_CAP_GET_CHALLENGE = 0x0040,
|
|
EXT_CAP_SM = 0x0080,
|
|
EXT_CAP_LCS = 0x0100,
|
|
EXT_CAP_CHAINING = 0x1000,
|
|
EXT_CAP_APDU_EXT = 0x2000,
|
|
EXT_CAP_MSE = 0x4000
|
|
} pgp_ext_caps_t;
|
|
|
|
typedef enum _pgp_card_state {
|
|
CARD_STATE_UNKNOWN = 0x00,
|
|
CARD_STATE_INITIALIZATION = 0x03,
|
|
CARD_STATE_ACTIVATED = 0x05
|
|
} pgp_card_state_t;
|
|
|
|
typedef enum _pgp_sm_algo {
|
|
SM_ALGO_NONE = 0, /* SM not supported */
|
|
SM_ALGO_AES128 = 1,
|
|
SM_ALGO_AES256 = 2,
|
|
SM_ALGO_SCP11b = 3,
|
|
SM_ALGO_3DES = 256, /* 2.x: coded as 0 in DO C0 */
|
|
SM_ALGO_UNKNOWN = 257 /* 3.x: coded as 0 in DO C0 */
|
|
} pgp_sm_algo_t;
|
|
|
|
typedef struct _pgp_do_info {
|
|
unsigned int id; /* ID of the DO in question */
|
|
|
|
pgp_do_type_t type; /* constructed DO or not */
|
|
pgp_access_t access; /* R/W access levels for the DO */
|
|
|
|
/* function to get the DO from the card:
|
|
* only != NULL is DO if readable and not only a part of a constructed DO */
|
|
int (*get_fn)(sc_card_t *, unsigned int, u8 *, size_t);
|
|
/* function to write the DO to the card:
|
|
* only != NULL if DO is writeable under some conditions */
|
|
int (*put_fn)(sc_card_t *, unsigned int, const u8 *, size_t);
|
|
} pgp_do_info_t;
|
|
|
|
typedef struct pgp_blob {
|
|
struct pgp_blob *next; /* pointer to next sibling */
|
|
struct pgp_blob *parent; /* pointer to parent */
|
|
pgp_do_info_t *info;
|
|
|
|
sc_file_t *file;
|
|
unsigned int id;
|
|
int status;
|
|
|
|
unsigned char *data;
|
|
unsigned int len;
|
|
struct pgp_blob *files; /* pointer to 1st child */
|
|
} pgp_blob_t;
|
|
|
|
|
|
/* The DO holding X.509 certificate is constructed but does not contain a child DO.
|
|
* We should notice this when building fake file system later. */
|
|
#define DO_CERT 0x7f21
|
|
/* Control Reference Template of private keys. Ref: Section 4.3.3.7 of OpenPGP card v2 spec.
|
|
* Here we treat them as DOs just for convenience */
|
|
#define DO_SIGN 0xb600
|
|
#define DO_ENCR 0xb800
|
|
#define DO_AUTH 0xa400
|
|
/* These DOs do not exist. They are defined and used just for ease of implementation */
|
|
#define DO_SIGN_SYM 0xb601
|
|
#define DO_ENCR_SYM 0xb801
|
|
#define DO_AUTH_SYM 0xa401
|
|
/* Private DOs */
|
|
#define DO_PRIV1 0x0101
|
|
#define DO_PRIV2 0x0102
|
|
#define DO_PRIV3 0x0103
|
|
#define DO_PRIV4 0x0104
|
|
/* Cardholder information DOs */
|
|
#define DO_CARDHOLDER 0x65
|
|
#define DO_NAME 0x5b
|
|
#define DO_LANG_PREF 0x5f2d
|
|
#define DO_SEX 0x5f35
|
|
|
|
|
|
/* Maximum length for response buffer when reading pubkey.
|
|
* This value is calculated with 4096-bit key length */
|
|
#define MAXLEN_RESP_PUBKEY 527
|
|
/* Gnuk only supports 1 key length (2048 bit) */
|
|
#define MAXLEN_RESP_PUBKEY_GNUK 271
|
|
|
|
/* Maximal size of a DO:
|
|
* v2.0+: max. certificate size it at bytes 5-6 of Extended Capabilities DO 00C0
|
|
* v3.0+: max. special DO size is at bytes 7-8 of Extended Capabilities DO 00C0
|
|
* Theoretically we should have the 64k, but we currently limit to 8k. */
|
|
#define MAX_OPENPGP_DO_SIZE 8192
|
|
|
|
|
|
typedef struct _pgp_ec_curves {
|
|
struct sc_object_id oid;
|
|
size_t size;
|
|
} pgp_ec_curves_t;
|
|
|
|
|
|
#define DRVDATA(card) ((struct pgp_priv_data *) ((card)->drv_data))
|
|
|
|
struct pgp_priv_data {
|
|
pgp_blob_t *mf;
|
|
pgp_blob_t *current; /* currently selected file */
|
|
|
|
pgp_version_t bcd_version;
|
|
pgp_do_info_t *pgp_objects;
|
|
|
|
pgp_card_state_t state; /* card state */
|
|
pgp_ext_caps_t ext_caps; /* extended capabilities */
|
|
|
|
pgp_sm_algo_t sm_algo; /* Secure Messaging algorithm */
|
|
|
|
size_t max_challenge_size;
|
|
size_t max_cert_size;
|
|
size_t max_specialDO_size;
|
|
|
|
pgp_ec_curves_t *ec_curves;
|
|
|
|
sc_security_env_t sec_env;
|
|
};
|
|
|
|
#define BCD2UCHAR(x) (((((x) & 0xF0) >> 4) * 10) + ((x) & 0x0F))
|
|
|
|
#endif
|