/** Sign data (set by SETDATA) with certificate id in line. */ gpg_error_t cmd_pksign (assuan_context_t ctx, char *line) { static const unsigned char rmd160_prefix[] = /* (1.3.36.3.2.1) */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; static const unsigned char md5_prefix[] = /* (1.2.840.113549.2.5) */ { 0x30, 0x2c, 0x30, 0x09, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; static const unsigned char sha1_prefix[] = /* (1.3.14.3.2.26) */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; static const unsigned char sha224_prefix[] = /* (2.16.840.1.101.3.4.2.4) */ { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C }; static const unsigned char sha256_prefix[] = /* (2.16.840.1.101.3.4.2.1) */ { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 }; static const unsigned char sha384_prefix[] = /* (2.16.840.1.101.3.4.2.2) */ { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 }; static const unsigned char sha512_prefix[] = /* (2.16.840.1.101.3.4.2.3) */ { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 }; gpg_err_code_t error = GPG_ERR_GENERAL; pkcs11h_certificate_id_t cert_id = NULL; pkcs11h_certificate_t cert = NULL; cmd_data_t *data = (cmd_data_t *)assuan_get_pointer (ctx); cmd_data_t *_data = data; int need_free__data = 0; int session_locked = 0; unsigned char *sig = NULL; size_t sig_len; char hash[100] = ""; enum { INJECT_NONE, INJECT_RMD160, INJECT_MD5, INJECT_SHA1, INJECT_SHA224, INJECT_SHA256, INJECT_SHA384, INJECT_SHA512 } inject = INJECT_NONE; if (data->data == NULL) { error = GPG_ERR_INV_DATA; goto cleanup; } while (*line != '\x0' && (isspace (*line) || *line == '-')) { if (*line == '-') { static const char *hashprm = "--hash="; char *p = line; while (*line != '\x0' && !isspace (*line)) { line++; } line++; if (!strncmp (p, hashprm, strlen (hashprm))) { p += strlen (hashprm); *(line-1) = '\0'; snprintf (hash, sizeof(hash), "%s", p); } } else { line++; } } if (*line == '\x0') { error = GPG_ERR_INV_DATA; goto cleanup; } /* * sender prefixed data with algorithm OID */ if (strcmp(hash, "")) { if (!strcmp(hash, "rmd160") && data->size == (0x14 + sizeof(rmd160_prefix)) && !memcmp (data->data, rmd160_prefix, sizeof (rmd160_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "rmd160") && data->size == 0x14) { inject = INJECT_RMD160; } else if (!strcmp(hash, "md5") && data->size == (0x10 + sizeof(md5_prefix)) && !memcmp (data->data, md5_prefix, sizeof (md5_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "md5") && data->size == 0x10) { inject = INJECT_MD5; } else if (!strcmp(hash, "sha1") && data->size == (0x14 + sizeof(sha1_prefix)) && !memcmp (data->data, sha1_prefix, sizeof (sha1_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "sha1") && data->size == 0x14) { inject = INJECT_SHA1; } else if (!strcmp(hash, "sha224") && data->size == (0x1c + sizeof(sha224_prefix)) && !memcmp (data->data, sha224_prefix, sizeof (sha224_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "sha224") && data->size == 0x1c) { inject = INJECT_SHA224; } else if (!strcmp(hash, "sha256") && data->size == (0x20 + sizeof(sha256_prefix)) && !memcmp (data->data, sha256_prefix, sizeof (sha256_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "sha256") && data->size == 0x20) { inject = INJECT_SHA256; } else if (!strcmp(hash, "sha384") && data->size == (0x30 + sizeof(sha384_prefix)) && !memcmp (data->data, sha384_prefix, sizeof (sha384_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "sha384") && data->size == 0x30) { inject = INJECT_SHA384; } else if (!strcmp(hash, "sha512") && data->size == (0x40 + sizeof(sha512_prefix)) && !memcmp (data->data, sha512_prefix, sizeof (sha512_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "sha512") && data->size == 0x40) { inject = INJECT_SHA512; } else { common_log (LOG_DEBUG, "unsupported hash algo (hash=%s,size=%d)", hash, data->size); error = GPG_ERR_UNSUPPORTED_ALGORITHM; goto cleanup; } } else { if ( data->size == 0x10 + sizeof (md5_prefix) || data->size == 0x14 + sizeof (sha1_prefix) || data->size == 0x14 + sizeof (rmd160_prefix) ) { if ( memcmp (data->data, md5_prefix, sizeof (md5_prefix)) && memcmp (data->data, sha1_prefix, sizeof (sha1_prefix)) && memcmp (data->data, rmd160_prefix, sizeof (rmd160_prefix)) ) { error = GPG_ERR_UNSUPPORTED_ALGORITHM; goto cleanup; } } else { /* * unknown hash algorithm; * gnupg's scdaemon forces to SHA1 */ inject = INJECT_SHA1; } } if (inject != INJECT_NONE) { const unsigned char *oid; size_t oid_size; switch (inject) { case INJECT_RMD160: oid = rmd160_prefix; oid_size = sizeof (rmd160_prefix); break; case INJECT_MD5: oid = md5_prefix; oid_size = sizeof (md5_prefix); break; case INJECT_SHA1: oid = sha1_prefix; oid_size = sizeof (sha1_prefix); break; case INJECT_SHA224: oid = sha224_prefix; oid_size = sizeof (sha224_prefix); break; case INJECT_SHA256: oid = sha256_prefix; oid_size = sizeof(sha256_prefix); break; case INJECT_SHA384: oid = sha384_prefix; oid_size = sizeof(sha384_prefix); break; case INJECT_SHA512: oid = sha512_prefix; oid_size = sizeof(sha512_prefix); break; default: error = GPG_ERR_INV_DATA; goto cleanup; } need_free__data = 1; if ((_data = (cmd_data_t *)malloc (sizeof (cmd_data_t))) == NULL) { error = GPG_ERR_ENOMEM; goto cleanup; } if ((_data->data = (unsigned char *)malloc (data->size + oid_size)) == NULL) { error = GPG_ERR_ENOMEM; goto cleanup; } _data->size = 0; memmove (_data->data+_data->size, oid, oid_size); _data->size += oid_size; memmove (_data->data+_data->size, data->data, data->size); _data->size += data->size; } if ( (error = _get_certificate_by_name ( ctx, line, OPENPGP_SIGN, &cert_id, NULL )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_create ( cert_id, ctx, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &cert ) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_lockSession (cert) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } session_locked = 1; if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_signAny ( cert, CKM_RSA_PKCS, _data->data, _data->size, NULL, &sig_len ) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ((sig = (unsigned char *)malloc (sig_len)) == NULL) { error = GPG_ERR_ENOMEM; goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_signAny ( cert, CKM_RSA_PKCS, _data->data, _data->size, sig, &sig_len ) )) != GPG_ERR_NO_ERROR || (error = assuan_send_data(ctx, sig, sig_len)) != GPG_ERR_NO_ERROR ) { goto cleanup; } error = GPG_ERR_NO_ERROR; cleanup: if (session_locked) { pkcs11h_certificate_releaseSession (cert); session_locked = 0; } if (cert != NULL) { pkcs11h_certificate_freeCertificate (cert); cert = NULL; } if (cert_id != NULL) { pkcs11h_certificate_freeCertificateId (cert_id); cert_id = NULL; } if (sig != NULL) { free (sig); sig = NULL; } if (need_free__data) { free (_data->data); _data->data = NULL; free (_data); _data = NULL; } return gpg_error (error); }
static int __pkcs11h_openssl_rsa_enc ( IN int flen, IN unsigned char *from, OUT unsigned char *to, IN OUT RSA *rsa, IN int padding ) { #else static int __pkcs11h_openssl_rsa_enc ( IN int flen, IN const unsigned char *from, OUT unsigned char *to, IN OUT RSA *rsa, IN int padding ) { #endif pkcs11h_certificate_t certificate = __pkcs11h_openssl_rsa_get_pkcs11h_certificate (rsa); PKCS11H_BOOL session_locked = FALSE; CK_RV rv = CKR_FUNCTION_FAILED; size_t tlen; _PKCS11H_ASSERT (from!=NULL); _PKCS11H_ASSERT (to!=NULL); _PKCS11H_ASSERT (rsa!=NULL); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: __pkcs11h_openssl_rsa_enc entered - flen=%d, from=%p, to=%p, rsa=%p, padding=%d", flen, from, to, (void *)rsa, padding ); if (padding != RSA_PKCS1_PADDING) { rv = CKR_MECHANISM_INVALID; goto cleanup; } tlen = (size_t)RSA_size(rsa); if ((rv = pkcs11h_certificate_lockSession (certificate)) != CKR_OK) { goto cleanup; } session_locked = TRUE; _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Performing signature" ); if ( (rv = pkcs11h_certificate_signAny ( certificate, CKM_RSA_PKCS, from, flen, to, &tlen )) != CKR_OK ) { _PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot perform signature %ld:'%s'", rv, pkcs11h_getMessage (rv)); goto cleanup; } rv = CKR_OK; cleanup: if (session_locked) { pkcs11h_certificate_releaseSession (certificate); session_locked = FALSE; } _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: __pkcs11h_openssl_rsa_enc - return rv=%lu-'%s'", rv, pkcs11h_getMessage (rv) ); return rv == CKR_OK ? (int)tlen : -1; }
/** Decrypt data (set by SETDATA) with certificate id in line. */ gpg_error_t cmd_pkdecrypt (assuan_context_t ctx, char *line) { gpg_err_code_t error = GPG_ERR_GENERAL; pkcs11h_certificate_id_t cert_id = NULL; pkcs11h_certificate_t cert = NULL; unsigned char *ptext = NULL; size_t ptext_len; int session_locked = 0; cmd_data_t *data = (cmd_data_t *)assuan_get_pointer (ctx); cmd_data_t _data; if ( data == NULL || data->data == NULL ) { error = GPG_ERR_INV_DATA; goto cleanup; } /* * Guess.. taken from openpgp card implementation * and java PKCS#11 provider. */ _data.data = data->data; _data.size = data->size; if ( *_data.data == 0 && ( _data.size == 129 || _data.size == 193 || _data.size == 257 || _data.size == 385 || _data.size == 513 ) ) { _data.data++; _data.size--; } if ( (error = _get_certificate_by_name ( ctx, line, OPENPGP_ENCR, &cert_id, NULL )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_create ( cert_id, ctx, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &cert ) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_lockSession (cert) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } session_locked = 1; if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_decryptAny ( cert, CKM_RSA_PKCS, _data.data, _data.size, NULL, &ptext_len ) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ((ptext = (unsigned char *)malloc (ptext_len)) == NULL) { error = GPG_ERR_ENOMEM; goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_decryptAny ( cert, CKM_RSA_PKCS, _data.data, _data.size, ptext, &ptext_len ) )) != GPG_ERR_NO_ERROR || (error = assuan_write_status(ctx, "PADDING", "0")) != GPG_ERR_NO_ERROR || (error = assuan_send_data(ctx, ptext, ptext_len)) != GPG_ERR_NO_ERROR ) { goto cleanup; } error = GPG_ERR_NO_ERROR; cleanup: if (session_locked) { pkcs11h_certificate_releaseSession (cert); session_locked = 0; } if (cert != NULL) { pkcs11h_certificate_freeCertificate (cert); cert = NULL; } if (cert_id != NULL) { pkcs11h_certificate_freeCertificateId (cert_id); cert_id = NULL; } if (ptext != NULL) { free (ptext); ptext = NULL; } return gpg_error (error); }
static int __pkcs11h_openssl_rsa_dec ( IN int flen, IN unsigned char *from, OUT unsigned char *to, IN OUT RSA *rsa, IN int padding ) { #else static int __pkcs11h_openssl_rsa_dec ( IN int flen, IN const unsigned char *from, OUT unsigned char *to, IN OUT RSA *rsa, IN int padding ) { #endif pkcs11h_certificate_t certificate = __pkcs11h_openssl_rsa_get_pkcs11h_certificate (rsa); PKCS11H_BOOL session_locked = FALSE; CK_MECHANISM_TYPE mech = CKM_RSA_PKCS; CK_RV rv = CKR_FUNCTION_FAILED; size_t tlen = (size_t)flen; _PKCS11H_ASSERT (from!=NULL); _PKCS11H_ASSERT (to!=NULL); _PKCS11H_ASSERT (rsa!=NULL); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: __pkcs11h_openssl_rsa_dec entered - flen=%d, from=%p, to=%p, rsa=%p, padding=%d", flen, from, to, (void *)rsa, padding ); switch (padding) { case RSA_PKCS1_PADDING: mech = CKM_RSA_PKCS; break; case RSA_PKCS1_OAEP_PADDING: mech = CKM_RSA_PKCS_OAEP; break; case RSA_SSLV23_PADDING: rv = CKR_MECHANISM_INVALID; break; case RSA_NO_PADDING: rv = CKR_MECHANISM_INVALID; break; } if (rv == CKR_MECHANISM_INVALID) goto cleanup; if ((rv = pkcs11h_certificate_lockSession (certificate)) != CKR_OK) { goto cleanup; } session_locked = TRUE; _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Performing decryption" ); if ( (rv = pkcs11h_certificate_decryptAny ( certificate, mech, from, flen, to, &tlen )) != CKR_OK ) { _PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot perform decryption %ld:'%s'", rv, pkcs11h_getMessage (rv)); goto cleanup; } rv = CKR_OK; cleanup: if (session_locked) { pkcs11h_certificate_releaseSession (certificate); session_locked = FALSE; } _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: __pkcs11h_openssl_rsa_dec - return rv=%lu-'%s'", rv, pkcs11h_getMessage (rv) ); return rv == CKR_OK ? (int)tlen : -1; }