1*9469f4f1Schristos /* $NetBSD: sshkey.h,v 1.21 2024/09/24 21:32:19 christos Exp $ */ 2*9469f4f1Schristos /* $OpenBSD: sshkey.h,v 1.65 2024/09/04 05:33:34 djm Exp $ */ 35484a5efSchristos 45484a5efSchristos /* 55484a5efSchristos * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 65484a5efSchristos * 75484a5efSchristos * Redistribution and use in source and binary forms, with or without 85484a5efSchristos * modification, are permitted provided that the following conditions 95484a5efSchristos * are met: 105484a5efSchristos * 1. Redistributions of source code must retain the above copyright 115484a5efSchristos * notice, this list of conditions and the following disclaimer. 125484a5efSchristos * 2. Redistributions in binary form must reproduce the above copyright 135484a5efSchristos * notice, this list of conditions and the following disclaimer in the 145484a5efSchristos * documentation and/or other materials provided with the distribution. 155484a5efSchristos * 165484a5efSchristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 175484a5efSchristos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 185484a5efSchristos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 195484a5efSchristos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 205484a5efSchristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 215484a5efSchristos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 225484a5efSchristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 235484a5efSchristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 245484a5efSchristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 255484a5efSchristos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265484a5efSchristos */ 275484a5efSchristos #ifndef SSHKEY_H 285484a5efSchristos #define SSHKEY_H 295484a5efSchristos 301b8bb90dSchristos #include "includes.h" 315484a5efSchristos #include <sys/types.h> 325484a5efSchristos 335484a5efSchristos #ifdef WITH_OPENSSL 345484a5efSchristos #include <openssl/rsa.h> 355484a5efSchristos #include <openssl/dsa.h> 365484a5efSchristos #include <openssl/ec.h> 37aa36fcacSchristos #include <openssl/ecdsa.h> 38*9469f4f1Schristos #include <openssl/evp.h> 3917418e98Schristos #define SSH_OPENSSL_VERSION OpenSSL_version(OPENSSL_VERSION) 405484a5efSchristos #else /* OPENSSL */ 41aa36fcacSchristos #define BIGNUM void 425484a5efSchristos #define RSA void 435484a5efSchristos #define DSA void 445484a5efSchristos #define EC_KEY void 455484a5efSchristos #define EC_GROUP void 465484a5efSchristos #define EC_POINT void 47*9469f4f1Schristos #define EVP_PKEY void 4817418e98Schristos #define SSH_OPENSSL_VERSION "without OpenSSL" 495484a5efSchristos #endif /* WITH_OPENSSL */ 505484a5efSchristos 517a183406Schristos #define SSH_RSA_MINIMUM_MODULUS_SIZE 1024 525484a5efSchristos #define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20) 535484a5efSchristos 545484a5efSchristos struct sshbuf; 555484a5efSchristos 565484a5efSchristos /* Key types */ 575484a5efSchristos enum sshkey_types { 585484a5efSchristos KEY_RSA, 595484a5efSchristos KEY_DSA, 605484a5efSchristos KEY_ECDSA, 615484a5efSchristos KEY_ED25519, 625484a5efSchristos KEY_RSA_CERT, 635484a5efSchristos KEY_DSA_CERT, 645484a5efSchristos KEY_ECDSA_CERT, 655484a5efSchristos KEY_ED25519_CERT, 66ffae97bbSchristos KEY_XMSS, 67ffae97bbSchristos KEY_XMSS_CERT, 68ed75d7a8Schristos KEY_ECDSA_SK, 69ed75d7a8Schristos KEY_ECDSA_SK_CERT, 70ed75d7a8Schristos KEY_ED25519_SK, 71ed75d7a8Schristos KEY_ED25519_SK_CERT, 725484a5efSchristos KEY_UNSPEC 735484a5efSchristos }; 745484a5efSchristos 75e161120fSchristos /* Default fingerprint hash */ 76e161120fSchristos #define SSH_FP_HASH_DEFAULT SSH_DIGEST_SHA256 775484a5efSchristos 785484a5efSchristos /* Fingerprint representation formats */ 795484a5efSchristos enum sshkey_fp_rep { 80e161120fSchristos SSH_FP_DEFAULT = 0, 815484a5efSchristos SSH_FP_HEX, 82e161120fSchristos SSH_FP_BASE64, 835484a5efSchristos SSH_FP_BUBBLEBABBLE, 845484a5efSchristos SSH_FP_RANDOMART 855484a5efSchristos }; 865484a5efSchristos 87ffae97bbSchristos /* Private key serialisation formats, used on the wire */ 88ffae97bbSchristos enum sshkey_serialize_rep { 89ffae97bbSchristos SSHKEY_SERIALIZE_DEFAULT = 0, 90ed75d7a8Schristos SSHKEY_SERIALIZE_STATE = 1, /* only state is serialized */ 91ed75d7a8Schristos SSHKEY_SERIALIZE_FULL = 2, /* include keys for saving to disk */ 92ed75d7a8Schristos SSHKEY_SERIALIZE_SHIELD = 3, /* everything, for encrypting in ram */ 93ed75d7a8Schristos SSHKEY_SERIALIZE_INFO = 254, /* minimal information */ 94ffae97bbSchristos }; 95ffae97bbSchristos 96cd4ada6aSchristos /* Private key disk formats */ 97cd4ada6aSchristos enum sshkey_private_format { 98cd4ada6aSchristos SSHKEY_PRIVATE_OPENSSH = 0, 99cd4ada6aSchristos SSHKEY_PRIVATE_PEM = 1, 100cd4ada6aSchristos SSHKEY_PRIVATE_PKCS8 = 2, 101cd4ada6aSchristos }; 102cd4ada6aSchristos 1035484a5efSchristos /* key is stored in external hardware */ 1045484a5efSchristos #define SSHKEY_FLAG_EXT 0x0001 1055484a5efSchristos 1065484a5efSchristos #define SSHKEY_CERT_MAX_PRINCIPALS 256 1075484a5efSchristos /* XXX opaquify? */ 1085484a5efSchristos struct sshkey_cert { 1095484a5efSchristos struct sshbuf *certblob; /* Kept around for use on wire */ 1105484a5efSchristos u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */ 1115484a5efSchristos u_int64_t serial; 1125484a5efSchristos char *key_id; 1135484a5efSchristos u_int nprincipals; 1145484a5efSchristos char **principals; 1155484a5efSchristos u_int64_t valid_after, valid_before; 1165484a5efSchristos struct sshbuf *critical; 1175484a5efSchristos struct sshbuf *extensions; 1185484a5efSchristos struct sshkey *signature_key; 119aa36fcacSchristos char *signature_type; 1205484a5efSchristos }; 1215484a5efSchristos 1225484a5efSchristos /* XXX opaquify? */ 1235484a5efSchristos struct sshkey { 1245484a5efSchristos int type; 1255484a5efSchristos int flags; 126ed75d7a8Schristos /* KEY_DSA */ 1275484a5efSchristos DSA *dsa; 128ed75d7a8Schristos /* KEY_ECDSA and KEY_ECDSA_SK */ 1295484a5efSchristos int ecdsa_nid; /* NID of curve */ 130*9469f4f1Schristos /* libcrypto-backed keys */ 131*9469f4f1Schristos EVP_PKEY *pkey; 132ed75d7a8Schristos /* KEY_ED25519 and KEY_ED25519_SK */ 1335484a5efSchristos u_char *ed25519_sk; 1345484a5efSchristos u_char *ed25519_pk; 135ed75d7a8Schristos /* KEY_XMSS */ 136ffae97bbSchristos char *xmss_name; 137ffae97bbSchristos char *xmss_filename; /* for state file updates */ 138ffae97bbSchristos void *xmss_state; /* depends on xmss_name, opaque */ 139ffae97bbSchristos u_char *xmss_sk; 140ffae97bbSchristos u_char *xmss_pk; 141ed75d7a8Schristos /* KEY_ECDSA_SK and KEY_ED25519_SK */ 142ed75d7a8Schristos char *sk_application; 143ed75d7a8Schristos uint8_t sk_flags; 144ed75d7a8Schristos struct sshbuf *sk_key_handle; 145ed75d7a8Schristos struct sshbuf *sk_reserved; 146ed75d7a8Schristos /* Certificates */ 1475484a5efSchristos struct sshkey_cert *cert; 148ed75d7a8Schristos /* Private key shielding */ 149cd4ada6aSchristos u_char *shielded_private; 150cd4ada6aSchristos size_t shielded_len; 151cd4ada6aSchristos u_char *shield_prekey; 152cd4ada6aSchristos size_t shield_prekey_len; 1535484a5efSchristos }; 1545484a5efSchristos 1555484a5efSchristos #define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES 1565484a5efSchristos #define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES 1575484a5efSchristos 158ed75d7a8Schristos /* Additional fields contained in signature */ 159ed75d7a8Schristos struct sshkey_sig_details { 160ed75d7a8Schristos uint32_t sk_counter; /* U2F signature counter */ 161ed75d7a8Schristos uint8_t sk_flags; /* U2F signature flags; see ssh-sk.h */ 162ed75d7a8Schristos }; 163ed75d7a8Schristos 164b1066cf3Schristos struct sshkey_impl_funcs { 165b1066cf3Schristos u_int (*size)(const struct sshkey *); /* optional */ 166b1066cf3Schristos int (*alloc)(struct sshkey *); /* optional */ 167b1066cf3Schristos void (*cleanup)(struct sshkey *); /* optional */ 168b1066cf3Schristos int (*equal)(const struct sshkey *, const struct sshkey *); 169b1066cf3Schristos int (*serialize_public)(const struct sshkey *, struct sshbuf *, 170b1066cf3Schristos enum sshkey_serialize_rep); 171b1066cf3Schristos int (*deserialize_public)(const char *, struct sshbuf *, 172b1066cf3Schristos struct sshkey *); 173b1066cf3Schristos int (*serialize_private)(const struct sshkey *, struct sshbuf *, 174b1066cf3Schristos enum sshkey_serialize_rep); 175b1066cf3Schristos int (*deserialize_private)(const char *, struct sshbuf *, 176b1066cf3Schristos struct sshkey *); 177b1066cf3Schristos int (*generate)(struct sshkey *, int); /* optional */ 178b1066cf3Schristos int (*copy_public)(const struct sshkey *, struct sshkey *); 179b1066cf3Schristos int (*sign)(struct sshkey *, u_char **, size_t *, 180b1066cf3Schristos const u_char *, size_t, const char *, 181b1066cf3Schristos const char *, const char *, u_int); /* optional */ 182b1066cf3Schristos int (*verify)(const struct sshkey *, const u_char *, size_t, 183b1066cf3Schristos const u_char *, size_t, const char *, u_int, 184b1066cf3Schristos struct sshkey_sig_details **); 185b1066cf3Schristos }; 186b1066cf3Schristos 187b1066cf3Schristos struct sshkey_impl { 188b1066cf3Schristos const char *name; 189b1066cf3Schristos const char *shortname; 190b1066cf3Schristos const char *sigalg; 191b1066cf3Schristos int type; 192b1066cf3Schristos int nid; 193b1066cf3Schristos int cert; 194b1066cf3Schristos int sigonly; 195b1066cf3Schristos int keybits; 196b1066cf3Schristos const struct sshkey_impl_funcs *funcs; 197b1066cf3Schristos }; 198b1066cf3Schristos 1995484a5efSchristos struct sshkey *sshkey_new(int); 2005484a5efSchristos void sshkey_free(struct sshkey *); 2015484a5efSchristos int sshkey_equal_public(const struct sshkey *, 2025484a5efSchristos const struct sshkey *); 2035484a5efSchristos int sshkey_equal(const struct sshkey *, const struct sshkey *); 2045484a5efSchristos char *sshkey_fingerprint(const struct sshkey *, 205e161120fSchristos int, enum sshkey_fp_rep); 2065484a5efSchristos int sshkey_fingerprint_raw(const struct sshkey *k, 207e161120fSchristos int, u_char **retp, size_t *lenp); 2085484a5efSchristos const char *sshkey_type(const struct sshkey *); 2095484a5efSchristos const char *sshkey_cert_type(const struct sshkey *); 2107a183406Schristos int sshkey_format_text(const struct sshkey *, struct sshbuf *); 2115484a5efSchristos int sshkey_write(const struct sshkey *, FILE *); 2125484a5efSchristos int sshkey_read(struct sshkey *, char **); 2135484a5efSchristos u_int sshkey_size(const struct sshkey *); 2145484a5efSchristos 2155484a5efSchristos int sshkey_generate(int type, u_int bits, struct sshkey **keyp); 2165484a5efSchristos int sshkey_from_private(const struct sshkey *, struct sshkey **); 217cd4ada6aSchristos 218cd4ada6aSchristos int sshkey_is_shielded(struct sshkey *); 219cd4ada6aSchristos int sshkey_shield_private(struct sshkey *); 220cd4ada6aSchristos int sshkey_unshield_private(struct sshkey *); 221cd4ada6aSchristos 2225484a5efSchristos int sshkey_type_from_name(const char *); 223*9469f4f1Schristos int sshkey_type_from_shortname(const char *); 2245484a5efSchristos int sshkey_is_cert(const struct sshkey *); 225ed75d7a8Schristos int sshkey_is_sk(const struct sshkey *); 2265484a5efSchristos int sshkey_type_is_cert(int); 2275484a5efSchristos int sshkey_type_plain(int); 228a03ec00cSchristos 229a03ec00cSchristos /* Returns non-zero if key name match sigalgs pattern list. (handles RSA) */ 230a03ec00cSchristos int sshkey_match_keyname_to_sigalgs(const char *, const char *); 231a03ec00cSchristos 232f453f1d4Schristos int sshkey_to_certified(struct sshkey *); 2335484a5efSchristos int sshkey_drop_cert(struct sshkey *); 2345484a5efSchristos int sshkey_cert_copy(const struct sshkey *, struct sshkey *); 23517418e98Schristos int sshkey_cert_check_authority(const struct sshkey *, int, int, int, 236b592f463Schristos uint64_t, const char *, const char **); 237b592f463Schristos int sshkey_cert_check_authority_now(const struct sshkey *, int, int, int, 2385484a5efSchristos const char *, const char **); 23917418e98Schristos int sshkey_cert_check_host(const struct sshkey *, const char *, 24017418e98Schristos int , const char *, const char **); 24148b02105Schristos size_t sshkey_format_cert_validity(const struct sshkey_cert *, 24248b02105Schristos char *, size_t) __attribute__((__bounded__(__string__, 2, 3))); 243aa36fcacSchristos int sshkey_check_cert_sigtype(const struct sshkey *, const char *); 2445484a5efSchristos 245ed75d7a8Schristos int sshkey_certify(struct sshkey *, struct sshkey *, 2462d3b0f52Schristos const char *, const char *, const char *); 2477a183406Schristos /* Variant allowing use of a custom signature function (e.g. for ssh-agent) */ 248cd4ada6aSchristos typedef int sshkey_certify_signer(struct sshkey *, u_char **, size_t *, 2492d3b0f52Schristos const u_char *, size_t, const char *, const char *, const char *, 2502d3b0f52Schristos u_int, void *); 2517a183406Schristos int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *, 2522d3b0f52Schristos const char *, const char *, sshkey_certify_signer *, void *); 2537a183406Schristos 2545484a5efSchristos int sshkey_ecdsa_nid_from_name(const char *); 2555484a5efSchristos int sshkey_curve_name_to_nid(const char *); 2565484a5efSchristos const char * sshkey_curve_nid_to_name(int); 2575484a5efSchristos u_int sshkey_curve_nid_to_bits(int); 2585484a5efSchristos int sshkey_ecdsa_bits_to_nid(int); 259*9469f4f1Schristos int sshkey_ecdsa_key_to_nid(const EC_KEY *); 260*9469f4f1Schristos int sshkey_ecdsa_pkey_to_nid(EVP_PKEY *); 2615484a5efSchristos int sshkey_ec_nid_to_hash_alg(int nid); 2625484a5efSchristos int sshkey_ec_validate_public(const EC_GROUP *, const EC_POINT *); 2635484a5efSchristos int sshkey_ec_validate_private(const EC_KEY *); 2645484a5efSchristos const char *sshkey_ssh_name(const struct sshkey *); 2655484a5efSchristos const char *sshkey_ssh_name_plain(const struct sshkey *); 266a629fefcSchristos int sshkey_names_valid2(const char *, int, int); 26741768fc1Schristos char *sshkey_alg_list(int, int, int, char); 2685484a5efSchristos 2695484a5efSchristos int sshkey_from_blob(const u_char *, size_t, struct sshkey **); 270e161120fSchristos int sshkey_fromb(struct sshbuf *, struct sshkey **); 271e161120fSchristos int sshkey_froms(struct sshbuf *, struct sshkey **); 2725484a5efSchristos int sshkey_to_blob(const struct sshkey *, u_char **, size_t *); 2730cf1df15Schristos int sshkey_to_base64(const struct sshkey *, char **); 274e161120fSchristos int sshkey_putb(const struct sshkey *, struct sshbuf *); 275e161120fSchristos int sshkey_puts(const struct sshkey *, struct sshbuf *); 276ffae97bbSchristos int sshkey_puts_opts(const struct sshkey *, struct sshbuf *, 277ffae97bbSchristos enum sshkey_serialize_rep); 2785484a5efSchristos int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *); 279e161120fSchristos int sshkey_putb_plain(const struct sshkey *, struct sshbuf *); 2805484a5efSchristos 281cd4ada6aSchristos int sshkey_sign(struct sshkey *, u_char **, size_t *, 2822d3b0f52Schristos const u_char *, size_t, const char *, const char *, const char *, u_int); 2835484a5efSchristos int sshkey_verify(const struct sshkey *, const u_char *, size_t, 284ed75d7a8Schristos const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); 28555a4608bSchristos int sshkey_check_sigtype(const u_char *, size_t, const char *); 28655a4608bSchristos const char *sshkey_sigalg_by_name(const char *); 287cd4ada6aSchristos int sshkey_get_sigtype(const u_char *, size_t, char **); 2885484a5efSchristos 289*9469f4f1Schristos /* Signing and verification backend for libcrypto-backed keys */ 290*9469f4f1Schristos int sshkey_pkey_digest_sign(EVP_PKEY*, int, u_char **, 291*9469f4f1Schristos size_t *, const u_char *, size_t); 292*9469f4f1Schristos int sshkey_pkey_digest_verify(EVP_PKEY *, int, const u_char *, 293*9469f4f1Schristos size_t, u_char *, size_t); 294*9469f4f1Schristos 2955484a5efSchristos /* for debug */ 2965484a5efSchristos void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *); 2975484a5efSchristos void sshkey_dump_ec_key(const EC_KEY *); 2985484a5efSchristos 2995484a5efSchristos /* private key parsing and serialisation */ 300cd4ada6aSchristos int sshkey_private_serialize(struct sshkey *key, struct sshbuf *buf); 301cd4ada6aSchristos int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, 302ffae97bbSchristos enum sshkey_serialize_rep); 3035484a5efSchristos int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp); 3045484a5efSchristos 3055484a5efSchristos /* private key file format parsing and serialisation */ 3065484a5efSchristos int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, 3075484a5efSchristos const char *passphrase, const char *comment, 308cd4ada6aSchristos int format, const char *openssh_format_cipher, int openssh_format_rounds); 3095484a5efSchristos int sshkey_parse_private_fileblob(struct sshbuf *buffer, 31048b02105Schristos const char *passphrase, struct sshkey **keyp, char **commentp); 3115484a5efSchristos int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, 3125484a5efSchristos const char *passphrase, struct sshkey **keyp, char **commentp); 3138db691beSchristos int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, 3148db691beSchristos int type, struct sshkey **pubkeyp); 3155484a5efSchristos 316e160b4e8Schristos int sshkey_check_rsa_length(const struct sshkey *, int); 3177a183406Schristos /* XXX should be internal, but used by ssh-keygen */ 318*9469f4f1Schristos int ssh_rsa_complete_crt_parameters(const BIGNUM *, const BIGNUM *, 319*9469f4f1Schristos const BIGNUM *, const BIGNUM *, BIGNUM **, BIGNUM **); 3207a183406Schristos 321ffae97bbSchristos /* stateful keys (e.g. XMSS) */ 322ffae97bbSchristos int sshkey_set_filename(struct sshkey *, const char *); 323ffae97bbSchristos int sshkey_enable_maxsign(struct sshkey *, u_int32_t); 324ffae97bbSchristos u_int32_t sshkey_signatures_left(const struct sshkey *); 32517418e98Schristos int sshkey_private_serialize_maxsign(struct sshkey *key, 32617418e98Schristos struct sshbuf *buf, u_int32_t maxsign, int); 327ffae97bbSchristos 328ed75d7a8Schristos void sshkey_sig_details_free(struct sshkey_sig_details *); 329ed75d7a8Schristos 330*9469f4f1Schristos #ifdef WITH_OPENSSL 331*9469f4f1Schristos int sshkey_ecdsa_fixup_group(EVP_PKEY *k); /* ssh-ecdsa.c */ 332*9469f4f1Schristos #endif 333*9469f4f1Schristos 3345484a5efSchristos #ifdef SSHKEY_INTERNAL 335b1066cf3Schristos int sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b); 336b1066cf3Schristos void sshkey_sk_cleanup(struct sshkey *k); 337b1066cf3Schristos int sshkey_serialize_sk(const struct sshkey *key, struct sshbuf *b); 338b1066cf3Schristos int sshkey_copy_public_sk(const struct sshkey *from, struct sshkey *to); 339b1066cf3Schristos int sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key); 340b1066cf3Schristos int sshkey_serialize_private_sk(const struct sshkey *key, 341b1066cf3Schristos struct sshbuf *buf); 342b1066cf3Schristos int sshkey_private_deserialize_sk(struct sshbuf *buf, struct sshkey *k); 343b1066cf3Schristos #ifdef WITH_OPENSSL 344b1066cf3Schristos int check_rsa_length(const RSA *rsa); /* XXX remove */ 345b1066cf3Schristos #endif 3465484a5efSchristos #endif 3475484a5efSchristos 3485484a5efSchristos #ifndef WITH_OPENSSL 3495484a5efSchristos #undef RSA 3505484a5efSchristos #undef DSA 3515484a5efSchristos #undef EC_KEY 3525484a5efSchristos #undef EC_GROUP 3535484a5efSchristos #undef EC_POINT 354*9469f4f1Schristos #undef EVP_PKEY 3555484a5efSchristos #endif /* WITH_OPENSSL */ 3565484a5efSchristos 3575484a5efSchristos #endif /* SSHKEY_H */ 358