static bool _cjose_jws_verify_sig_ps(cjose_jws_t *jws, const cjose_jwk_t *jwk, cjose_err *err) { bool retval = false; uint8_t *em = NULL; size_t em_len = 0; // ensure jwk is RSA if (jwk->kty != CJOSE_JWK_KTY_RSA) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto _cjose_jws_verify_sig_ps_cleanup; } // make sure we have an alg header json_t *alg_obj = json_object_get(jws->hdr, CJOSE_HDR_ALG); if (NULL == alg_obj) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); return false; } const char *alg = json_string_value(alg_obj); // build digest using SHA-256/384/512 digest algorithm const EVP_MD *digest_alg = NULL; if (strcmp(alg, CJOSE_HDR_ALG_PS256) == 0) digest_alg = EVP_sha256(); else if (strcmp(alg, CJOSE_HDR_ALG_PS384) == 0) digest_alg = EVP_sha384(); else if (strcmp(alg, CJOSE_HDR_ALG_PS512) == 0) digest_alg = EVP_sha512(); if (NULL == digest_alg) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jws_verify_sig_ps_cleanup; } // allocate buffer for encoded message em_len = RSA_size((RSA *)jwk->keydata); em = (uint8_t *)cjose_get_alloc()(em_len); if (NULL == em) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jws_verify_sig_ps_cleanup; } // decrypt signature if (RSA_public_decrypt(jws->sig_len, jws->sig, em, (RSA *)jwk->keydata, RSA_NO_PADDING) != em_len) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jws_verify_sig_ps_cleanup; } // verify decrypted signature data against PSS encoded digest if (RSA_verify_PKCS1_PSS((RSA *)jwk->keydata, jws->dig, digest_alg, em, -1) != 1) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jws_verify_sig_ps_cleanup; } // if we got this far - success retval = true; _cjose_jws_verify_sig_ps_cleanup: cjose_get_dealloc()(em); return retval; }
int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding) { const unsigned rsa_size = RSA_size(rsa); BIGNUM *f, *result; int ret = 0; int r = -1; uint8_t *buf = NULL; BN_CTX *ctx = NULL; if (max_out < rsa_size) { OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL); return 0; } if (!check_modulus_and_exponent_sizes(rsa)) { return 0; } ctx = BN_CTX_new(); if (ctx == NULL) { goto err; } BN_CTX_start(ctx); f = BN_CTX_get(ctx); result = BN_CTX_get(ctx); if (padding == RSA_NO_PADDING) { buf = out; } else { /* Allocate a temporary buffer to hold the padded plaintext. */ buf = OPENSSL_malloc(rsa_size); if (buf == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } } if (!f || !result) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } if (in_len != rsa_size) { OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN); goto err; } if (BN_bin2bn(in, in_len, f) == NULL) { goto err; } if (BN_ucmp(f, rsa->n) >= 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; } if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) { if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) == NULL) { goto err; } } if (!rsa->meth->bn_mod_exp(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) { goto err; } if (!BN_bn2bin_padded(buf, rsa_size, result)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } switch (padding) { case RSA_PKCS1_PADDING: r = RSA_padding_check_PKCS1_type_1(out, rsa_size, buf, rsa_size); break; case RSA_NO_PADDING: r = rsa_size; break; default: OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); goto err; } if (r < 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED); } else { *out_len = r; ret = 1; } err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (padding != RSA_NO_PADDING && buf != NULL) { OPENSSL_cleanse(buf, rsa_size); OPENSSL_free(buf); } return ret; }
void openssl_rsa_crypt() { RSA *r; BIO *b; BIGNUM *bne; unsigned int len; int size, elen, dlen; unsigned char inputs[COMM_LEN] = "rsa crypt"; unsigned char tmps[MAX1_LEN], outputs[MAX1_LEN]; memset(tmps, 0, sizeof(tmps)); memset(outputs, 0, sizeof(outputs)); printf("\nRSA generate key:\n"); bne = BN_new(); BN_set_word(bne, RSA_3); r = RSA_new(); RSA_generate_key_ex(r, MAX1_LEN, bne, NULL); RSA_print_fp(stdout, r, 11); b = BIO_new_file("/tmp/rsa.key", "w"); i2d_RSAPrivateKey_bio(b, r); BIO_free(b); elen = RSA_private_encrypt(RSA_size(r) - 11, inputs, outputs, r, RSA_PKCS1_PADDING); dlen = RSA_public_decrypt(elen, outputs, tmps, r, RSA_PKCS1_PADDING); if (elen <= 0 || dlen <= 0 || memcmp(inputs, tmps, RSA_size(r) - 11)) { printf("RSA_private_encrypt error!\n"); RSA_free(r); return; } printf("RSA_private_encrypt(%s) = ", inputs); for (size = 0; size < elen; size++) printf("%02x", outputs[size]); printf("\n"); memset(outputs, 0, sizeof(outputs)); elen = RSA_public_encrypt(RSA_size(r) - 11, inputs, outputs, r, RSA_PKCS1_PADDING); dlen = RSA_private_decrypt(elen, outputs, tmps, r, RSA_PKCS1_PADDING); if (elen <= 0 || dlen <= 0 || memcmp(inputs, tmps, RSA_size(r) - 11)) { printf("RSA_public_encrypt error!\n"); RSA_free(r); return; } printf("RSA_public_encrypt(%s) = ", inputs); for (size = 0; size < elen; size++) printf("%02x", outputs[size]); printf("\n"); memset(outputs, 0, sizeof(outputs)); RSA_sign(NID_md5_sha1, inputs, 36, outputs, &len, r); printf("RSA_sign(%s) = ", inputs); for (size = 0; size < len; size++) printf("%02x", outputs[size]); printf("\n"); memset(tmps, 0, sizeof(tmps)); RSA_verify(NID_md5_sha1, inputs, 36, outputs, len, r); printf("RSA_verify("); for (size = 0; size < len; size++) printf("%02x", outputs[size]); printf(") = %s\n", inputs); RSA_free(r); }
int bdd_do_select ( char *safe_trame ) { // Déclaration variable char* morceau = NULL ; // Variable contenant chaque morceau de la trame (strtok_r) char* statut = NULL ; char* affectation = NULL ; char* groupes = NULL ; char* reference = NULL ; int cpt = 0 ; // Compteur MYSQL_RES* resultat_req ; // Object MYSQL décrivant le résultat d'une requête MYSQL_ROW tuple ; // Object MYSQL décrivant un tuple dans la liste résultat char* safe_tuple = NULL ; // Permet d'appeler strtok_r sur le bon contenu. char* valeur = NULL ; char* politique = NULL ; int code_retour = 0 ; // On découpe les 4 éléments restant de notre trame for ( cpt = 0; cpt < 4; cpt++ ) { // On découpe la trame en morceaux repérés via un "*" if ( ( morceau = strtok_r ( NULL, "*", &safe_trame ) ) == NULL ) { perror ( "Erreur_bdd_do_select : information manquante " ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On vérifie que l'information est présente if ( strcmp ( morceau, "EOF") == 0 ) { perror ( "Erreur_bdd_do_select : information manquante II" ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } else { // On affecte l'information switch ( cpt ) { case ZERO : statut = morceau ; break ; case UN : affectation = morceau ; break ; case DEUX : groupes = morceau ; break ; case TROIS : reference = morceau ; break ; default : perror ( "Erreur_do_select : overflow compteur cpt " ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; break ; } } } // On récupère auprès de la BDD, la valeur associée à cette référence if ( bdd_do_request ( mysql_bdd, SELECT, reference, NULL, &resultat_req ) == ERRNO ) { perror ( "Erreur_bdd_do_select : bad requete " ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On récupère le tuple if ( ( tuple = mysql_fetch_row ( resultat_req ) ) == NULL ) { perror ( "Erreur_bdd_do_select : bad tuple " ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On déchiffre le tuple char* output = (char*) malloc ( RSA_size ( bdd_key ) * sizeof ( char ) ) ; memset ( output, '\0', RSA_size ( bdd_key ) ) ; if ( RSA_chiffrement ( (unsigned char*) tuple[0], (unsigned char*) output, DECHIFFREMENT ) != TRUE ) { perror ( "Erreur_bdd_do_select : RSA_dechiffrement " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On récupère les 3 informations du tuple morceau = NULL ; for ( cpt = 0; cpt < 3; cpt++ ) { // On découpe le tuple en morceaux repérés via un "*" if ( cpt == 0 ) morceau = strtok_r ( output, "*", &safe_tuple ) ; else morceau = strtok_r ( NULL, "*", &safe_tuple ) ; // Vérification if ( morceau == NULL ) { perror ( "Erreur_bdd_do_select : information manquante III " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On affecte l'information switch ( cpt ) { case ZERO : break ; case UN : valeur = morceau ; break ; case DEUX : politique = morceau ; break ; default : perror ( "Erreur_do_select : overflow compteur cpt " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; break ; } } // On regarde les politique de partage de la ressource morceau = NULL ; safe_tuple = NULL ; for ( cpt = 0; cpt < 3; cpt++ ) { // On découpe les politiques de partage en morceaux repérés via un "$" if ( cpt == 0 ) morceau = strtok_r ( politique, "$", &safe_tuple ) ; else morceau = strtok_r ( NULL, "$", &safe_tuple ) ; if ( morceau == NULL ) { perror ( "Erreur_bdd_do_select : information manquante IV " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On regarde d'abord si on est en accès interdit if ( strcmp ( morceau, "-" ) == 0 ) { printf ( "Erreur_bdd_do_select : BAD-PERMISSION " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "BAD-PERMISSION" ) ; return FALSE ; } else if ( strcmp ( morceau, "+") != 0 ) // Puis si on n'est pas en accès total { // Alors on traite le cas par cas switch ( cpt ) { case ZERO : // Statut code_retour = bdd_verification_partage ( morceau, statut ) ; break ; case UN : // Affectation code_retour = bdd_verification_partage ( morceau, affectation ) ; break ; case DEUX : // Groupes code_retour = bdd_verification_partage ( morceau, groupes ) ; break ; default : perror ( "Erreur_do_select : overflow compteur cpt " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; break ; } // On vérifie le code retour if ( code_retour == FALSE ) { printf ( "Erreur_bdd_do_select : bad permission " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "BAD-PERMISSION" ) ; return FALSE ; } else if ( code_retour == ERRNO ) { printf ( "Erreur_bdd_do_select : bdd_verification_partage " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } } } // Si on arrive ici c'est que la poltique de partage est respectée : on retourne la valeur int taille = strlen ( valeur ) + 10 ; char* reponse = (char*) malloc ( taille * sizeof ( char ) ) ; memset ( reponse, '\0', taille ) ; sprintf ( reponse, "%d*%s*EOF", SELECT, valeur ) ; res_send ( reponse ) ; // On free l'espace de résultat free ( output ) ; mysql_free_result ( resultat_req ) ; free ( reponse ) ; // On indique que tout s'est bien déroulé return TRUE ; }
int bdd_do_request ( MYSQL* mysql_bdd, int action, char* reference, char* valeur, MYSQL_RES** resultat_req ) { // Initialisation char *requete = (char*) malloc ( TAILLE_REQUETE * sizeof ( char ) ) ; memset ( requete, '\0', TAILLE_REQUETE ) ; int return_value ; // On prépare la zone mémoire de sortie (chiffrement) int i = 0 ; int good = FALSE ; char* insertion = (char*) malloc ( RSA_size ( bdd_key ) * sizeof ( char ) ) ; memset ( insertion, '\0', RSA_size ( bdd_key ) ) ; // Chiffrement BDD if ( action == INSERT ) { // On vérifie la taille du buffer d'entrée if ( strlen ( valeur ) <= ( TAILLE_MAX_UTILE - 1 ) ) { // Tant que le chiffré n'est pas bon while ( good != TRUE ) { // Ini memset ( insertion, '\0', RSA_size ( bdd_key ) ) ; // On chiffre if ( RSA_chiffrement ( (unsigned char*) valeur, (unsigned char*) insertion, CHIFFREMENT ) != TRUE ) { perror ( "Erreur_bdd_do_request : RSA_chiffrement " ) ; free ( insertion ) ; free ( requete ) ; return ERRNO ; } // On suppose chiffré bon good = TRUE ; // On vérifie la non présence du caractère ", \ et \0 for ( i = 0; i < TAILLE_MAX_RSA; i ++ ) { if ( ( (int) insertion[i] == APOSTROPHE ) || ( (int) insertion[i] == BACK_SLASH ) || ( (int) insertion[i] == ZERO_TERMINAL ) ) good = FALSE ; } } } } // On prépare la requête selon l'action à faire switch ( action ) { case SELECT_ALL : sprintf ( requete, "select REF, VAL from %s;", TABLE ) ; break ; case SELECT : sprintf ( requete, "select VAL from %s where REF = \"%s\";", TABLE, reference ) ; break ; case INSERT : sprintf ( requete, "insert into %s (REF, VAL) values(\"%s\",\"%s\");", TABLE, reference, insertion ) ; break ; case DELETE : sprintf ( requete, "delete from %s where REF = \"%s\";", TABLE, reference ) ; break ; case DELETE_ALL : sprintf ( requete, "delete from %s;", TABLE ) ; break ; default : perror ( "Erreur_bdd_do_request : bad action " ) ; free ( requete ) ; free ( insertion ) ; return ERRNO ; break ; } // On réalise la requête if ( ( return_value = mysql_query ( mysql_bdd, requete ) ) != 0 ) { fprintf ( stderr, "Erreur_bdd_do_request : mysql_query avec code action : %d \n", action ) ; fprintf ( stderr, "Erreur_bdd_do_request : mysql_query avec requete : %s \n", requete ) ; fprintf ( stderr, "Erreur_bdd_do_request : mysql_query avec retour : %d \n", return_value ) ; free ( requete ) ; free ( insertion ) ; return ERRNO ; } // Selon l'action réalisée, on récupère des résultats if ( ( action == SELECT_ALL ) || ( action == SELECT ) ) { if ( ( *resultat_req = mysql_use_result ( mysql_bdd ) ) == NULL ) { perror ( "Erreur_bdd_do_request : mysql_use_result " ) ; free ( requete ) ; free ( insertion ) ; return ERRNO ; } } // Free free ( requete ) ; free ( insertion ) ; // On indique que tout s'est bien déroulé return TRUE ; }
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ int ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen) { const EVP_MD *evp_md; EVP_MD_CTX md; u_char digest[EVP_MAX_MD_SIZE], *sig; u_int slen, dlen, len; int ok, nid; Buffer b; if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) { pamsshagentauth_logerror("ssh_rsa_sign: no RSA key"); return -1; } nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { pamsshagentauth_logerror("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid); return -1; } EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); slen = RSA_size(key->rsa); sig = pamsshagentauth_xmalloc(slen); ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); memset(digest, 'd', sizeof(digest)); if (ok != 1) { int ecode = ERR_get_error(); pamsshagentauth_logerror("ssh_rsa_sign: RSA_sign failed: %s", ERR_error_string(ecode, NULL)); pamsshagentauth_xfree(sig); return -1; } if (len < slen) { u_int diff = slen - len; pamsshagentauth_verbose("slen %u > len %u", slen, len); memmove(sig + diff, sig, len); memset(sig, 0, diff); } else if (len > slen) { pamsshagentauth_logerror("ssh_rsa_sign: slen %u slen2 %u", slen, len); pamsshagentauth_xfree(sig); return -1; } /* encode signature */ pamsshagentauth_buffer_init(&b); pamsshagentauth_buffer_put_cstring(&b, "ssh-rsa"); pamsshagentauth_buffer_put_string(&b, sig, slen); len = pamsshagentauth_buffer_len(&b); if (lenp != NULL) *lenp = len; if (sigp != NULL) { *sigp = pamsshagentauth_xmalloc(len); memcpy(*sigp, pamsshagentauth_buffer_ptr(&b), len); } pamsshagentauth_buffer_free(&b); memset(sig, 's', slen); pamsshagentauth_xfree(sig); return 0; }
/* called by CSPFullPluginSession */ void RSA_CryptContext::init(const Context &context, bool encoding /*= true*/) { StLock<Mutex> _(gMutex()); if(mInitFlag && !opStarted()) { /* reusing - e.g. query followed by encrypt */ return; } /* optional mode to use alternate key class (e.g., decrypt with public key) */ CSSM_KEYCLASS keyClass; switch (context.getInt(CSSM_ATTRIBUTE_MODE)) { case CSSM_ALGMODE_PUBLIC_KEY: keyClass = CSSM_KEYCLASS_PUBLIC_KEY; break; case CSSM_ALGMODE_PRIVATE_KEY: keyClass = CSSM_KEYCLASS_PRIVATE_KEY; break; case CSSM_ALGMODE_NONE: /* default, not present in context: infer from op type */ keyClass = encoding ? CSSM_KEYCLASS_PUBLIC_KEY : CSSM_KEYCLASS_PRIVATE_KEY; break; default: CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE); } /* fetch key from context */ if(mRsaKey == NULL) { assert(!opStarted()); CSSM_DATA label = {0, NULL}; mRsaKey = contextToRsaKey(context, session(), keyClass, encoding ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, mAllocdRsaKey, label); if(label.Data) { mLabel.copy(label); mOaep = true; free(label.Data); } } else { assert(opStarted()); } unsigned cipherBlockSize = RSA_size(mRsaKey); unsigned plainBlockSize; /* padding - not present means value zero, CSSM_PADDING_NONE */ uint32 padding = context.getInt(CSSM_ATTRIBUTE_PADDING); switch(padding) { case CSSM_PADDING_NONE: mPadding = RSA_NO_PADDING; plainBlockSize = cipherBlockSize; break; case CSSM_PADDING_PKCS1: mPadding = RSA_PKCS1_PADDING; plainBlockSize = cipherBlockSize - 11; break; case CSSM_PADDING_APPLE_SSLv2: rsaCryptDebug("RSA_CryptContext::init using CSSM_PADDING_APPLE_SSLv2"); mPadding = RSA_SSLV23_PADDING; plainBlockSize = cipherBlockSize - 11; break; default: rsaCryptDebug("RSA_CryptContext::init bad padding (0x%x)", (unsigned)padding); CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING); } /* optional blinding attribute */ uint32 blinding = context.getInt(CSSM_ATTRIBUTE_RSA_BLINDING); if(blinding) { if(RSA_blinding_on(mRsaKey, NULL) <= 0) { /* actually no legit failures */ CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); } } else { RSA_blinding_off(mRsaKey); } /* finally, have BlockCryptor set up its stuff. */ setup(encoding ? plainBlockSize : cipherBlockSize, // blockSizeIn encoding ? cipherBlockSize : plainBlockSize, // blockSizeOut false, // pkcs5Pad false, // needsFinal BCM_ECB, NULL); // IV mInitFlag = true; }
static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { int ret; RSA_PKEY_CTX *rctx = ctx->data; RSA *rsa = ctx->pkey->pkey.rsa; if (rctx->md) { if (tbslen != (size_t)EVP_MD_size(rctx->md)) { RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_INVALID_DIGEST_LENGTH); return -1; } if (EVP_MD_type(rctx->md) == NID_mdc2) { unsigned int sltmp; if (rctx->pad_mode != RSA_PKCS1_PADDING) return -1; ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp, rsa); if (ret <= 0) return ret; ret = sltmp; } else if (rctx->pad_mode == RSA_X931_PADDING) { if ((size_t)EVP_PKEY_size(ctx->pkey) < tbslen + 1) { RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_KEY_SIZE_TOO_SMALL); return -1; } if (!setup_tbuf(rctx, ctx)) { RSAerr(RSA_F_PKEY_RSA_SIGN, ERR_R_MALLOC_FAILURE); return -1; } memcpy(rctx->tbuf, tbs, tbslen); rctx->tbuf[tbslen] = RSA_X931_hash_id(EVP_MD_type(rctx->md)); ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf, sig, rsa, RSA_X931_PADDING); } else if (rctx->pad_mode == RSA_PKCS1_PADDING) { unsigned int sltmp; ret = RSA_sign(EVP_MD_type(rctx->md), tbs, tbslen, sig, &sltmp, rsa); if (ret <= 0) return ret; ret = sltmp; } else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) { if (!setup_tbuf(rctx, ctx)) return -1; if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa, rctx->tbuf, tbs, rctx->md, rctx->mgf1md, rctx->saltlen)) return -1; ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf, sig, rsa, RSA_NO_PADDING); } else { return -1; } } else { ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa, rctx->pad_mode); } if (ret < 0) return ret; *siglen = ret; return 1; }
ssh_string ssh_encrypt_rsa1(ssh_session session, ssh_string data, ssh_public_key key) { ssh_string str = NULL; size_t len = string_len(data); size_t size = 0; #ifdef HAVE_LIBGCRYPT const char *tmp = NULL; gcry_sexp_t ret_sexp; gcry_sexp_t data_sexp; if (gcry_sexp_build(&data_sexp, NULL, "(data(flags pkcs1)(value %b))", len, string_data(data))) { ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error"); return NULL; } if (gcry_pk_encrypt(&ret_sexp, data_sexp, key->rsa_pub)) { gcry_sexp_release(data_sexp); ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error"); return NULL; } gcry_sexp_release(data_sexp); data_sexp = gcry_sexp_find_token(ret_sexp, "a", 0); if (data_sexp == NULL) { ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error"); gcry_sexp_release(ret_sexp); return NULL; } tmp = gcry_sexp_nth_data(data_sexp, 1, &size); if (*tmp == 0) { size--; tmp++; } str = string_new(size); if (str == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); gcry_sexp_release(data_sexp); gcry_sexp_release(ret_sexp); return NULL; } string_fill(str, tmp, size); gcry_sexp_release(data_sexp); gcry_sexp_release(ret_sexp); #elif defined HAVE_LIBCRYPTO size = RSA_size(key->rsa_pub); str = string_new(size); if (str == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); return NULL; } if (RSA_public_encrypt(len, string_data(data), string_data(str), key->rsa_pub, RSA_PKCS1_PADDING) < 0) { string_free(str); return NULL; } #endif return str; }
int main(int argc, char *argv[]) { /* Variabili e strutture standard per la gestione della connessione */ int ret; int cl_sk; int cl_ret; struct sockaddr_in sv_addr; /* Passare, oltre a indirizzo IP e porta (del server), anche la password condivisa con il server */ if(argc != 4) { cerr << "Errore: sintassi del comando errata" << endl; cout << "Digitare: ./client <indirizzo_IP> <porta> <password_condivisa>" << endl; exit(1); } SERVER_IP_ADD = argv[1]; SERVER_PORT = atoi(argv[2]); CLIENT_PWD = argv[3]; cout << endl; cout << "********* INIZIO FASE DI CONNESSIONE ********" << endl; int np = strlen(CLIENT_PWD); //Numero di caratteri che compongono la password if(np < 8) { cerr << "Errore: inserire una password di almeno 8 caratteri alfanumerici e/o caratteri speciali" << endl; exit(1); } if(SERVER_PORT <= 1023) { cerr << "Porta <" << SERVER_PORT << "> non utilizzabile :: Well Known Port" << endl; return -1; } if(SERVER_PORT <= 65535 && SERVER_PORT >= 49152) cout << "Fare attenzione nella scelta della porta <" << SERVER_PORT << "> :: Dynamic and/or Private Port" << endl; /* Creazione del socket lato client */ cl_sk = socket(AF_INET, SOCK_STREAM, 0); if(cl_sk == -1) { cerr << "Errore: funzione <socket> non eseguita correttamente sul client" << endl; exit(0); } /* Inizializzazione struttura dati */ bzero(&sv_addr, sizeof(struct sockaddr_in)); /* Azzera il contenuto della struttura */ sv_addr.sin_family = AF_INET; sv_addr.sin_port = htons(SERVER_PORT); inet_pton(AF_INET, SERVER_IP_ADD, &sv_addr.sin_addr.s_addr); /* Converte l'indirizzo da stringa a valore numerico */ cl_ret = connect(cl_sk, (struct sockaddr *)(&sv_addr), sizeof(struct sockaddr_in)); if(cl_ret == -1) { cerr << "Errore: funzione <connect> non eseguita correttamente sul client" << endl; exit(0); } cout << endl; cout << "\033[32mCONNESSIONE CLIENT-SERVER EFFETTUATA\033[0m" << endl; cout << "\033[32mIndirizzo IP server: " << SERVER_IP_ADD << "\033[0m" << endl; cout << "\033[32mPorta server: " << SERVER_PORT << "\033[0m" << endl; cout << "\033[32mDescrittore del soket lato client in ascolto: " << cl_sk << "\033[0m" << endl; cout << endl; cout << "********** FINE FASE DI CONNESSIONE *********" << endl; cout << endl; cout << "---------------------------------------------" << endl; cout << endl; cout << "****** INIZIO FASE DI SCAMBIO MESSAGGI ******" << endl; cout << endl; /* Setto l'identificatore del client e del server */ CLIENT = 'C'; SERVER = 'S'; /* Costrutisco il messaggio M1 */ msg1 m1; m1.client = CLIENT; m1.server = SERVER; /* Invio al server il messaggio M1 */ int dim1 = sizeof(msg1); ret = send(cl_sk, &m1, dim1, 0); if(ret == -1) { cerr << "Errore: messaggio M1 non inviato correttamente" << endl; return -1; } cout << "\033[32m:: C -> S\033[0m" << endl; cout << "\033[34m:: Messaggio in chiaro M1 inviato al server\033[0m" << endl; cout << endl; /* Ricevo dal server il messaggio M2 */ msg2 m2; int dim2 = sizeof(msg2); ret = recv(cl_sk, &m2, dim2, MSG_WAITALL); if(ret == -1) { cerr << "Errore: messaggio M2 non ricevuto correttamente" << endl; return -1; } /* Memorizzo il nounce ricevuto dal server */ NOUNCE = m2.nounce; cout << "\033[32m:: S -> C\033[0m" << endl; cout << "\033[34m:: Messaggio in chiaro M2 ricevuto correttamente\033[0m" << endl; cout << endl; /* Setto la chiave pubblica con cui criptare M3 */ FILE *pub = fopen(PUB_KEY, "r"); RSA *pub_key = RSA_new(); PEM_read_RSA_PUBKEY(pub, &pub_key, NULL, NULL); /* Converto il nounce in una stringa per poterlo inserire nel messaggio da cifrare */ char tmp[50]; int n; //Numero di caratteri che compongono il nounce n = sprintf(tmp, "%i", NOUNCE); //Converto il nounce in una stringa char nounce[n]; strcpy(nounce, tmp); /* Genero le componenti della chiave di sessione in maniera random */ int part1 = rand(); char tmp1[50]; int t1 = sprintf(tmp1, "%i", part1); char p1[t1]; strcpy(p1, tmp1); int part2 = rand(); char tmp2[50]; int t2 = sprintf(tmp2, "%i", part2); char p2[t2]; strcpy(p2, tmp2); int part3 = rand(); char tmp3[50]; int t3 = sprintf(tmp3, "%i", part3); char p3[t3]; strcpy(p3, tmp3); /* Costruisco la chiave di sessione */ int dim_ses = t1 + t2 + t3; //Numero di caratteri della chiave di sessione char *ses_key = (char*) malloc (dim_ses); bzero(ses_key, dim_ses); strcpy(ses_key, p1); strcat(ses_key, p2); strcat(ses_key, p3); /* Setto la chiave di sessione */ BF_KEY kcs; BF_set_key(&kcs, dim_ses, (const unsigned char*)ses_key); /* Costruisco il messaggio M3 da criptare e inviare al client */ int sep3 = 4; //Numero di separatori da inserire nel messaggio M3 int ids3 = 2; //Numero di identificatori da inserire nel messaggio M3 int dim3 = ids3 + n + np + dim_ses + sep3; char *m3 = (char*) malloc(dim3 + 1); bzero(m3, dim3 + 1); strcpy(m3, "C"); strcat(m3, " "); strcat(m3, "S"); strcat(m3, " "); strcat(m3, nounce); strcat(m3, " "); strcat(m3, CLIENT_PWD); strcat(m3, " "); strcat(m3, ses_key); /* Cripto il messaggio M3 con la chiave pubblica */ unsigned char *m3c = (unsigned char*) malloc(RSA_size(pub_key)); bzero(m3c, RSA_size(pub_key)); int nc; //Numero di byte restituiti dalla cifratura nc = RSA_public_encrypt(dim3, (unsigned char*)m3, m3c, pub_key, RSA_PKCS1_OAEP_PADDING); if(nc == -1) { cerr << "Errore: funzione <RSA_public_encrypt> sul messaggio M3 non effettuata con successo" << endl; exit(1); } if(nc == 0) { cerr << "Errore: messaggio M3 non criptato correttamente" << endl; exit(1); } /* Invio al server la dimensione del messaggio cifrato */ int dim3c = RSA_size(pub_key); ret = send(cl_sk, &dim3c, 4, 0); if(ret == -1) { cerr << "Errore: dimensione del messaggio cifrato M3 non inviata correttamente" << endl; return -1; } /* Invio al server il messaggio cifrato M3 */ ret = send(cl_sk, m3c, dim3c, 0); if(ret == -1) { cerr << "Errore: messaggio cifrato M3 non inviato correttamente" << endl; return -1; } cout << "\033[32m:: C -> S\033[0m" << endl; cout << "\033[34m:: Messaggio cifrato M3 inviato al server\033[0m" << endl; cout << endl; /* Ricevo dal server la dimensione il messaggio criptato M4 */ int dim4c; ret = recv(cl_sk, &dim4c, 4, MSG_WAITALL); if(ret == -1) { cerr << "Errore: dimensione del messaggio cifrato M4 non ricevuta correttamente" << endl; return -1; } /* Imposto la dimensione del messaggio criptato M4 */ double b = 8.0; //Numero di byte -> dimensione del blocco cifrato int dim4cb = (int)ceil(dim4c / b) * 8; dim4cb++; /* Ricevo dal server il messaggio criptato M4 */ unsigned char *m4c = (unsigned char*) malloc(dim4cb); bzero(m4c, dim4cb); ret = recv(cl_sk, m4c, dim4cb, MSG_WAITALL); if(ret == -1) { cerr << "Errore: dimensione del messaggio cifrato M4 non ricevuta correttamente" << endl; return -1; } cout << "\033[32m:: S -> C\033[0m" << endl; cout << "\033[34m:: Messaggio cifrato M4 ricevuto correttamente\033[0m" << endl; /* Decifro il messaggio criptato M4 */ unsigned char *m4 = (unsigned char*) malloc(dim4c); bzero(m4, dim4c); int off = 0; //Offeset for(int i = 0; i < (int)ceil(dim4c / b); i++) { BF_ecb_encrypt(m4c + off, &m4[off], &kcs, BF_DECRYPT); off+=b; } cout << "\t\033[31m:: Messaggio cifrato M4 decriptato correttamente\033[0m" << endl; /* Analizzo il messaggio decriptato M4 */ char *s4 = strtok((char*)m4, " "); //Memorizzo l'id del server char *c4 = strtok(NULL, " "); //Memorizzo l'id del client char *p4 = strtok(NULL, " "); //Memorizzo la password /* Controllo che la password sia quella attesa */ if(strcmp(p4, CLIENT_PWD) != 0) { cout << "La password non coincide con quella attesa" << endl; exit(0); } else { cout << "\033[31m\t:: Controllo Password -> OK\033[0m" << endl; } cout << endl; cout << "******* FINE FASE DI SCAMBIO MESSAGGI *******" << endl; cout << endl; cout << "---------------------------------------------" << endl; cout << endl; /* Pulizia delle variabili inutilizzate per evitare warning */ strcpy(c4, ""); strcpy(s4, ""); cout << "************ INIZIO FASE DI TEST ************" << endl; cout << endl; /* Apertura del file per effettuare il test */ fstream ft; ft.open(TEST, ios::in); if(!ft) { cerr << "Errore nell'apertura del file di test" << endl; exit(0); } /* Memorizzo il file di test in una stringa */ char *test_tmp = (char*) malloc(MAX_FILE_LEN); bzero(test_tmp, MAX_FILE_LEN); char line[MAX_LINE_LEN]; while(ft.getline(line, MAX_LINE_LEN)) { strcat(test_tmp, line); } /* Alloco lo spazio effettivamente utilizzato dal file di test */ int dimtest = strlen(test_tmp) + 1; char *test = (char*) malloc(dimtest+1); bzero(test, dimtest); strcpy(test,test_tmp); /* Invio al server la dimensione del messaggio in chiaro */ ret = send(cl_sk, &dimtest, 4, 0); if(ret == -1) { cerr << "Errore: dimensione del messaggio di test in chiaro non inviata correttamente" << endl; return -1; } /* Imposto la dimensione del messaggio di test criptato */ int dimtestc = (int)ceil(dimtest / b) * 8; dimtestc++; /* Cripto la stringa del file di test */ unsigned char *testc = (unsigned char*) malloc(dimtestc); bzero(testc, dimtestc); int offtest = 0; for(int j = 0; j < (int)ceil(dimtest / b); j++) { BF_ecb_encrypt((const unsigned char*)test + offtest, &testc[offtest], &kcs, BF_ENCRYPT); offtest += b; } /* Invio al server la dimensione della stringa di test cifrata */ ret = send(cl_sk, &dimtestc, 4, 0); if(ret == -1) { cerr << "Errore: dimensione del messaggio di test cifrato non inviata correttamente" << endl; return -1; } /* Invio al server la stringa di test cifrata */ ret = send(cl_sk, testc, dimtestc, 0); if(ret == -1) { cerr << "Errore: messaggio di test cifrato non inviato correttamente" << endl; return -1; } cout << "\033[32m:: C -> S\033[0m" << endl; cout << "\033[34m:: Messaggio di test cifrato e inviato al server\033[0m" << endl; cout << endl; cout << "************* FINE FASE DI TEST *************" << endl; cout << endl; /* Libero la memoria */ RSA_free(pub_key); fclose(pub); free(m3); free(m3c); free(ses_key); free(m4c); free(m4); free(test_tmp); free(test); free(testc); return 0; }
/* Pre-processes and outputs RSA public key to standard out. */ void output(RSA* key) { int i, nwords; const BIGNUM *key_n; BIGNUM *N = NULL; BIGNUM *Big1 = NULL, *Big2 = NULL, *Big32 = NULL, *BigMinus1 = NULL; BIGNUM *B = NULL; BIGNUM *N0inv= NULL, *R = NULL, *RR = NULL, *RRTemp = NULL, *NnumBits = NULL; BIGNUM *n = NULL, *rr = NULL; BN_CTX *bn_ctx = BN_CTX_new(); uint32_t n0invout; /* Output size of RSA key in 32-bit words */ nwords = RSA_size(key) / 4; if (-1 == write(1, &nwords, sizeof(nwords))) goto failure; /* Initialize BIGNUMs */ RSA_get0_key(key, &key_n, NULL, NULL); N = BN_dup(key_n); Big1 = BN_new(); Big2 = BN_new(); Big32 = BN_new(); BigMinus1 = BN_new(); N0inv= BN_new(); R = BN_new(); RR = BN_new(); RRTemp = BN_new(); NnumBits = BN_new(); n = BN_new(); rr = BN_new(); BN_set_word(Big1, 1L); BN_set_word(Big2, 2L); BN_set_word(Big32, 32L); BN_sub(BigMinus1, Big1, Big2); B = BN_new(); BN_exp(B, Big2, Big32, bn_ctx); /* B = 2^32 */ /* Calculate and output N0inv = -1 / N[0] mod 2^32 */ BN_mod_inverse(N0inv, N, B, bn_ctx); BN_sub(N0inv, B, N0inv); n0invout = BN_get_word(N0inv); if (-1 == write(1, &n0invout, sizeof(n0invout))) goto failure; /* Calculate R = 2^(# of key bits) */ BN_set_word(NnumBits, BN_num_bits(N)); BN_exp(R, Big2, NnumBits, bn_ctx); /* Calculate RR = R^2 mod N */ BN_copy(RR, R); BN_mul(RRTemp, RR, R, bn_ctx); BN_mod(RR, RRTemp, N, bn_ctx); /* Write out modulus as little endian array of integers. */ for (i = 0; i < nwords; ++i) { uint32_t nout; BN_mod(n, N, B, bn_ctx); /* n = N mod B */ nout = BN_get_word(n); if (-1 == write(1, &nout, sizeof(nout))) goto failure; BN_rshift(N, N, 32); /* N = N/B */ } /* Write R^2 as little endian array of integers. */ for (i = 0; i < nwords; ++i) { uint32_t rrout; BN_mod(rr, RR, B, bn_ctx); /* rr = RR mod B */ rrout = BN_get_word(rr); if (-1 == write(1, &rrout, sizeof(rrout))) goto failure; BN_rshift(RR, RR, 32); /* RR = RR/B */ } failure: /* Free BIGNUMs. */ BN_free(N); BN_free(Big1); BN_free(Big2); BN_free(Big32); BN_free(BigMinus1); BN_free(N0inv); BN_free(R); BN_free(RRTemp); BN_free(NnumBits); BN_free(n); BN_free(rr); }
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; }
int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, const EVP_MD *Hash, const EVP_MD *mgf1Hash, const unsigned char *EM, int sLen) { int i; int ret = 0; int hLen, maskedDBLen, MSBits, emLen; const unsigned char *H; unsigned char *DB = NULL; EVP_MD_CTX ctx; unsigned char H_[EVP_MAX_MD_SIZE]; EVP_MD_CTX_init(&ctx); if (mgf1Hash == NULL) mgf1Hash = Hash; hLen = EVP_MD_size(Hash); if (hLen < 0) goto err; /*- * Negative sLen has special meanings: * -1 sLen == hLen * -2 salt length is autorecovered from signature * -N reserved */ if (sLen == -1) sLen = hLen; else if (sLen == -2) sLen = -2; else if (sLen < -2) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); goto err; } MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; emLen = RSA_size(rsa); if (EM[0] & (0xFF << MSBits)) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_FIRST_OCTET_INVALID); goto err; } if (MSBits == 0) { EM++; emLen--; } if (emLen < (hLen + sLen + 2)) { /* sLen can be small negative */ RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE); goto err; } if (EM[emLen - 1] != 0xbc) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_LAST_OCTET_INVALID); goto err; } maskedDBLen = emLen - hLen - 1; H = EM + maskedDBLen; DB = OPENSSL_malloc(maskedDBLen); if (!DB) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, ERR_R_MALLOC_FAILURE); goto err; } if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0) goto err; for (i = 0; i < maskedDBLen; i++) DB[i] ^= EM[i]; if (MSBits) DB[0] &= 0xFF >> (8 - MSBits); for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++) ; if (DB[i++] != 0x1) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_RECOVERY_FAILED); goto err; } if (sLen >= 0 && (maskedDBLen - i) != sLen) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); goto err; } if (!EVP_DigestInit_ex(&ctx, Hash, NULL) || !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) || !EVP_DigestUpdate(&ctx, mHash, hLen)) goto err; if (maskedDBLen - i) { if (!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i)) goto err; } if (!EVP_DigestFinal_ex(&ctx, H_, NULL)) goto err; if (sgx_memcmp(H_, H, hLen)) { RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_BAD_SIGNATURE); ret = 0; } else ret = 1; err: if (DB) OPENSSL_free(DB); EVP_MD_CTX_cleanup(&ctx); return ret; }
int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, const unsigned char *mHash, const EVP_MD *Hash, const EVP_MD *mgf1Hash, int sLen) { int i; int ret = 0; int hLen, maskedDBLen, MSBits, emLen; unsigned char *H, *salt = NULL, *p; EVP_MD_CTX ctx; if (mgf1Hash == NULL) mgf1Hash = Hash; hLen = EVP_MD_size(Hash); if (hLen < 0) goto err; /*- * Negative sLen has special meanings: * -1 sLen == hLen * -2 salt length is maximized * -N reserved */ if (sLen == -1) sLen = hLen; else if (sLen == -2) sLen = -2; else if (sLen < -2) { RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); goto err; } MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; emLen = RSA_size(rsa); if (MSBits == 0) { *EM++ = 0; emLen--; } if (sLen == -2) { sLen = emLen - hLen - 2; } else if (emLen < (hLen + sLen + 2)) { RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); goto err; } if (sLen > 0) { salt = OPENSSL_malloc(sLen); if (!salt) { RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, ERR_R_MALLOC_FAILURE); goto err; } if (RAND_bytes(salt, sLen) <= 0) goto err; } maskedDBLen = emLen - hLen - 1; H = EM + maskedDBLen; EVP_MD_CTX_init(&ctx); if (!EVP_DigestInit_ex(&ctx, Hash, NULL) || !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) || !EVP_DigestUpdate(&ctx, mHash, hLen)) goto err; if (sLen && !EVP_DigestUpdate(&ctx, salt, sLen)) goto err; if (!EVP_DigestFinal_ex(&ctx, H, NULL)) goto err; EVP_MD_CTX_cleanup(&ctx); /* Generate dbMask in place then perform XOR on it */ if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash)) goto err; p = EM; /* * Initial PS XORs with all zeroes which is a NOP so just update pointer. * Note from a test above this value is guaranteed to be non-negative. */ p += emLen - sLen - hLen - 2; *p++ ^= 0x1; if (sLen > 0) { for (i = 0; i < sLen; i++) *p++ ^= salt[i]; } if (MSBits) EM[0] &= 0xFF >> (8 - MSBits); /* H is already in place so just set final 0xbc */ EM[emLen - 1] = 0xbc; ret = 1; err: if (salt) OPENSSL_free(salt); return ret; }
int fips_check_rsa(RSA *rsa) { int n, ret = 0; unsigned char tctext[256], *ctext = tctext; unsigned char tptext[256], *ptext = tptext; /* The longest we can have with PKCS#1 v1.5 padding and a 512 bit key, * namely 512/8-11-1 = 52 bytes */ static const unsigned char original_ptext[] = "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef" "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef" "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef" "\x01\x23\x45\x67"; if (RSA_size(rsa) > sizeof(tctext)) { ctext = OPENSSL_malloc(RSA_size(rsa)); ptext = OPENSSL_malloc(RSA_size(rsa)); if (!ctext || !ptext) { ERR_print_errors_fp(OPENSSL_stderr()); exit(1); } } /* this will fail for keys shorter than 512 bits */ n=RSA_private_encrypt(sizeof(original_ptext)-1,original_ptext,ctext,rsa, RSA_PKCS1_PADDING); if(n < 0) { ERR_print_errors_fp(OPENSSL_stderr()); exit(1); } if(!memcmp(ctext,original_ptext,n)) { FIPSerr(FIPS_F_FIPS_CHECK_RSA,FIPS_R_PAIRWISE_TEST_FAILED); goto error; } n=RSA_public_decrypt(n,ctext,ptext,rsa,RSA_PKCS1_PADDING); if(n < 0) { ERR_print_errors_fp(OPENSSL_stderr()); exit(1); } if(n != sizeof(original_ptext)-1 || memcmp(ptext,original_ptext,n)) { FIPSerr(FIPS_F_FIPS_CHECK_RSA,FIPS_R_PAIRWISE_TEST_FAILED); goto error; } ret = 1; error: if (RSA_size(rsa) > sizeof(tctext)) { OPENSSL_free(ctext); OPENSSL_free(ptext); } return ret; }
/* TODO : split this function in two so it becomes smaller */ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature, ssh_public_key pubkey, int needed_type) { SIGNATURE *sign = NULL; ssh_buffer tmpbuf = NULL; ssh_string rs = NULL; ssh_string type_s = NULL; ssh_string e = NULL; char *type_c = NULL; int type; int len; int rsalen; #ifdef HAVE_LIBGCRYPT gcry_sexp_t sig; #elif defined HAVE_LIBCRYPTO DSA_SIG *sig = NULL; ssh_string r = NULL; ssh_string s = NULL; #endif sign = malloc(sizeof(SIGNATURE)); if (sign == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); return NULL; } tmpbuf = buffer_new(); if (tmpbuf == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); signature_free(sign); return NULL; } if (buffer_add_data(tmpbuf, string_data(signature), string_len(signature)) < 0) { signature_free(sign); buffer_free(tmpbuf); return NULL; } type_s = buffer_get_ssh_string(tmpbuf); if (type_s == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid signature packet"); signature_free(sign); buffer_free(tmpbuf); return NULL; } type_c = string_to_char(type_s); string_free(type_s); if (type_c == NULL) { signature_free(sign); buffer_free(tmpbuf); return NULL; } type = ssh_type_from_name(type_c); SAFE_FREE(type_c); if (needed_type != type) { ssh_set_error(session, SSH_FATAL, "Invalid signature type: %s", ssh_type_to_char(type)); signature_free(sign); buffer_free(tmpbuf); return NULL; } switch(needed_type) { case TYPE_DSS: rs = buffer_get_ssh_string(tmpbuf); buffer_free(tmpbuf); /* 40 is the dual signature blob len. */ if (rs == NULL || string_len(rs) != 40) { string_free(rs); signature_free(sign); return NULL; } /* we make use of strings (because we have all-made functions to convert * them to bignums (ou pas ;) */ #ifdef HAVE_LIBGCRYPT if (gcry_sexp_build(&sig, NULL, "(sig-val(dsa(r %b)(s %b)))", 20 ,string_data(rs), 20,(unsigned char *)string_data(rs) + 20)) { string_free(rs); signature_free(sign); return NULL; } #elif defined HAVE_LIBCRYPTO r = string_new(20); s = string_new(20); if (r == NULL || s == NULL) { string_free(r); string_free(s); string_free(rs); signature_free(sign); return NULL; } string_fill(r, string_data(rs), 20); string_fill(s, (char *)string_data(rs) + 20, 20); sig = DSA_SIG_new(); if (sig == NULL) { string_free(r); string_free(s); string_free(rs); signature_free(sign); return NULL; } sig->r = make_string_bn(r); /* is that really portable ? Openssh's hack isn't better */ sig->s = make_string_bn(s); string_free(r); string_free(s); if (sig->r == NULL || sig->s == NULL) { string_free(rs); DSA_SIG_free(sig); signature_free(sign); return NULL; } #endif #ifdef DEBUG_CRYPTO ssh_print_hexa("r", string_data(rs), 20); ssh_print_hexa("s", (const unsigned char *)string_data(rs) + 20, 20); #endif string_free(rs); sign->type = TYPE_DSS; sign->dsa_sign = sig; return sign; case TYPE_RSA: e = buffer_get_ssh_string(tmpbuf); buffer_free(tmpbuf); if (e == NULL) { signature_free(sign); return NULL; } len = string_len(e); #ifdef HAVE_LIBGCRYPT rsalen = (gcry_pk_get_nbits(pubkey->rsa_pub) + 7) / 8; #elif defined HAVE_LIBCRYPTO rsalen = RSA_size(pubkey->rsa_pub); #endif if (len > rsalen) { string_free(e); signature_free(sign); ssh_set_error(session, SSH_FATAL, "Signature too big! %d instead of %d", len, rsalen); return NULL; } if (len < rsalen) { ssh_log(session, SSH_LOG_RARE, "RSA signature len %d < %d", len, rsalen); } sign->type = TYPE_RSA; #ifdef HAVE_LIBGCRYPT if (gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))", string_len(e), string_data(e))) { signature_free(sign); string_free(e); return NULL; } sign->rsa_sign = sig; #elif defined HAVE_LIBCRYPTO sign->rsa_sign = e; #endif #ifdef DEBUG_CRYPTO ssh_log(session, SSH_LOG_FUNCTIONS, "len e: %d", len); ssh_print_hexa("RSA signature", string_data(e), len); #endif #ifdef HAVE_LIBGCRYPT string_free(e); #endif return sign; default: return NULL; } return NULL; }
int ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { Buffer b; const EVP_MD *evp_md; EVP_MD_CTX md; char *ktype; u_char digest[EVP_MAX_MD_SIZE], *sigblob; u_int len, dlen, modlen; int rlen, ret, nid; if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) { pamsshagentauth_logerror("ssh_rsa_verify: no RSA key"); return -1; } if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { pamsshagentauth_logerror("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits", BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); return -1; } pamsshagentauth_buffer_init(&b); pamsshagentauth_buffer_append(&b, signature, signaturelen); ktype = pamsshagentauth_buffer_get_string(&b, NULL); if (strcmp("ssh-rsa", ktype) != 0) { pamsshagentauth_logerror("ssh_rsa_verify: cannot handle type %s", ktype); pamsshagentauth_buffer_free(&b); pamsshagentauth_xfree(ktype); return -1; } pamsshagentauth_xfree(ktype); sigblob = pamsshagentauth_buffer_get_string(&b, &len); rlen = pamsshagentauth_buffer_len(&b); pamsshagentauth_buffer_free(&b); if (rlen != 0) { pamsshagentauth_logerror("ssh_rsa_verify: remaining bytes in signature %d", rlen); pamsshagentauth_xfree(sigblob); return -1; } /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key->rsa); if (len > modlen) { pamsshagentauth_logerror("ssh_rsa_verify: len %u > modlen %u", len, modlen); pamsshagentauth_xfree(sigblob); return -1; } else if (len < modlen) { u_int diff = modlen - len; pamsshagentauth_verbose("ssh_rsa_verify: add padding: modlen %u > len %u", modlen, len); sigblob = pamsshagentauth_xrealloc(sigblob, 1, modlen); memmove(sigblob + diff, sigblob, len); memset(sigblob, 0, diff); len = modlen; } nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { pamsshagentauth_logerror("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); pamsshagentauth_xfree(sigblob); return -1; } EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); memset(digest, 'd', sizeof(digest)); memset(sigblob, 's', len); pamsshagentauth_xfree(sigblob); pamsshagentauth_verbose("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); return ret; }
int RSAKeyImpl::size() const { return RSA_size(_pRSA); }
int AuthenticateAgent(AgentConnection *conn, bool trust_key) { char sendbuffer[CF_EXPANDSIZE], in[CF_BUFSIZE], *out, *decrypted_cchall; BIGNUM *nonce_challenge, *bn = NULL; unsigned char digest[EVP_MAX_MD_SIZE]; int encrypted_len, nonce_len = 0, len, session_size; bool need_to_implicitly_trust_server; char enterprise_field = 'c'; RSA *server_pubkey = NULL; if ((PUBKEY == NULL) || (PRIVKEY == NULL)) { /* Try once more to load the keys, maybe the system is converging. */ LoadSecretKeys(); if ((PUBKEY == NULL) || (PRIVKEY == NULL)) { char *pubkeyfile = PublicKeyFile(GetWorkDir()); Log(LOG_LEVEL_ERR, "No public/private key pair found at: %s", pubkeyfile); free(pubkeyfile); return false; } } enterprise_field = CfEnterpriseOptions(); session_size = CfSessionKeySize(enterprise_field); /* Generate a random challenge to authenticate the server */ nonce_challenge = BN_new(); if (nonce_challenge == NULL) { Log(LOG_LEVEL_ERR, "Cannot allocate BIGNUM structure for server challenge"); return false; } BN_rand(nonce_challenge, CF_NONCELEN, 0, 0); nonce_len = BN_bn2mpi(nonce_challenge, in); if (FIPS_MODE) { HashString(in, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(in, nonce_len, digest, HASH_METHOD_MD5); } /* We assume that the server bound to the remote socket is the official one i.e. = root's */ /* Ask the server to send us the public key if we don't have it. */ if ((server_pubkey = HavePublicKeyByIP(conn->username, conn->remoteip))) { need_to_implicitly_trust_server = false; encrypted_len = RSA_size(server_pubkey); } else { need_to_implicitly_trust_server = true; encrypted_len = nonce_len; } // Server pubkey is what we want to has as a unique ID snprintf(sendbuffer, sizeof(sendbuffer), "SAUTH %c %d %d %c", need_to_implicitly_trust_server ? 'n': 'y', encrypted_len, nonce_len, enterprise_field); out = xmalloc(encrypted_len); if (server_pubkey != NULL) { if (RSA_public_encrypt(nonce_len, in, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { Log(LOG_LEVEL_ERR, "Public encryption failed. (RSA_public_encrypt: %s)", CryptoLastErrorString()); free(out); RSA_free(server_pubkey); return false; } memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, out, encrypted_len); } else { memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, in, nonce_len); } /* proposition C1 - Send challenge / nonce */ SendTransaction(conn->conn_info, sendbuffer, CF_RSA_PROTO_OFFSET + encrypted_len, CF_DONE); BN_free(bn); BN_free(nonce_challenge); free(out); /*Send the public key - we don't know if server has it */ /* proposition C2 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->n, sendbuffer); SendTransaction(conn->conn_info, sendbuffer, len, CF_DONE); /* No need to encrypt the public key ... */ /* proposition C3 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->e, sendbuffer); SendTransaction(conn->conn_info, sendbuffer, len, CF_DONE); /* check reply about public key - server can break conn_info here */ /* proposition S1 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->conn_info, in, NULL) == -1) { Log(LOG_LEVEL_ERR, "Protocol transaction broken off (1). (ReceiveTransaction: %s)", GetErrorStr()); RSA_free(server_pubkey); return false; } if (BadProtoReply(in)) { Log(LOG_LEVEL_ERR, "Bad protocol reply: %s", in); RSA_free(server_pubkey); return false; } /* Get challenge response - should be CF_DEFAULT_DIGEST of challenge */ /* proposition S2 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->conn_info, in, NULL) == -1) { Log(LOG_LEVEL_ERR, "Protocol transaction broken off (2). (ReceiveTransaction: %s)", GetErrorStr()); RSA_free(server_pubkey); return false; } /* Check if challenge reply was correct */ if ((HashesMatch(digest, in, CF_DEFAULT_DIGEST)) || (HashesMatch(digest, in, HASH_METHOD_MD5))) // Legacy { if (need_to_implicitly_trust_server == false) { /* The IP was found in lastseen. */ Log(LOG_LEVEL_VERBOSE, ".....................[.h.a.i.l.]................................."); Log(LOG_LEVEL_VERBOSE, "Strong authentication of server '%s' connection confirmed", conn->this_server); } else /* IP was not found in lastseen */ { if (trust_key) { Log(LOG_LEVEL_VERBOSE, "Trusting server identity, promise to accept key from '%s' = '%s'", conn->this_server, conn->remoteip); } else { Log(LOG_LEVEL_ERR, "Not authorized to trust public key of server '%s' (trustkey = false)", conn->this_server); RSA_free(server_pubkey); return false; } } } else { Log(LOG_LEVEL_ERR, "Challenge response from server '%s/%s' was incorrect", conn->this_server, conn->remoteip); RSA_free(server_pubkey); return false; } /* Receive counter challenge from server */ /* proposition S3 */ memset(in, 0, CF_BUFSIZE); encrypted_len = ReceiveTransaction(conn->conn_info, in, NULL); if (encrypted_len <= 0) { Log(LOG_LEVEL_ERR, "Protocol transaction sent illegal cipher length"); RSA_free(server_pubkey); return false; } decrypted_cchall = xmalloc(encrypted_len); if (RSA_private_decrypt(encrypted_len, in, decrypted_cchall, PRIVKEY, RSA_PKCS1_PADDING) <= 0) { Log(LOG_LEVEL_ERR, "Private decrypt failed, abandoning. (RSA_private_decrypt: %s)", CryptoLastErrorString()); RSA_free(server_pubkey); return false; } /* proposition C4 */ if (FIPS_MODE) { HashString(decrypted_cchall, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(decrypted_cchall, nonce_len, digest, HASH_METHOD_MD5); } if (FIPS_MODE) { SendTransaction(conn->conn_info, digest, CF_DEFAULT_DIGEST_LEN, CF_DONE); } else { SendTransaction(conn->conn_info, digest, CF_MD5_LEN, CF_DONE); } free(decrypted_cchall); /* If we don't have the server's public key, it will be sent */ if (server_pubkey == NULL) { RSA *newkey = RSA_new(); Log(LOG_LEVEL_VERBOSE, "Collecting public key from server!"); /* proposition S4 - conditional */ if ((len = ReceiveTransaction(conn->conn_info, in, NULL)) <= 0) { Log(LOG_LEVEL_ERR, "Protocol error in RSA authentation from IP '%s'", conn->this_server); return false; } if ((newkey->n = BN_mpi2bn(in, len, NULL)) == NULL) { Log(LOG_LEVEL_ERR, "Private key decrypt failed. (BN_mpi2bn: %s)", CryptoLastErrorString()); RSA_free(newkey); return false; } /* proposition S5 - conditional */ if ((len = ReceiveTransaction(conn->conn_info, in, NULL)) <= 0) { Log(LOG_LEVEL_INFO, "Protocol error in RSA authentation from IP '%s'", conn->this_server); RSA_free(newkey); return false; } if ((newkey->e = BN_mpi2bn(in, len, NULL)) == NULL) { Log(LOG_LEVEL_ERR, "Public key decrypt failed. (BN_mpi2bn: %s)", CryptoLastErrorString()); RSA_free(newkey); return false; } server_pubkey = RSAPublicKey_dup(newkey); RSA_free(newkey); } assert(server_pubkey != NULL); /* proposition C5 */ if (!SetSessionKey(conn)) { Log(LOG_LEVEL_ERR, "Unable to set session key"); return false; } if (conn->session_key == NULL) { Log(LOG_LEVEL_ERR, "A random session key could not be established"); RSA_free(server_pubkey); return false; } encrypted_len = RSA_size(server_pubkey); out = xmalloc(encrypted_len); if (RSA_public_encrypt(session_size, conn->session_key, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { Log(LOG_LEVEL_ERR, "Public encryption failed. (RSA_public_encrypt: %s)", CryptoLastErrorString()); free(out); RSA_free(server_pubkey); return false; } SendTransaction(conn->conn_info, out, encrypted_len, CF_DONE); Key *key = KeyNew(server_pubkey, CF_DEFAULT_DIGEST); conn->conn_info->remote_key = key; Log(LOG_LEVEL_VERBOSE, "Public key identity of host '%s' is: %s", conn->remoteip, KeyPrintableHash(conn->conn_info->remote_key)); SavePublicKey(conn->username, KeyPrintableHash(conn->conn_info->remote_key), server_pubkey); unsigned int length = 0; LastSaw(conn->remoteip, KeyBinaryHash(conn->conn_info->remote_key, &length), LAST_SEEN_ROLE_CONNECT); free(out); return true; }
int RSA_verify(int type, const unsigned char *from, unsigned int flen, unsigned char *sigbuf, unsigned int siglen, RSA *rsa) { if (rsa->meth->rsa_verify) return rsa->meth->rsa_verify(type, from, flen, sigbuf, siglen, rsa); if (rsa->meth->rsa_pub_dec) { const AlgorithmIdentifier *digest_alg; void *data; DigestInfo di; size_t size; int ret, ret2; data = malloc(RSA_size(rsa)); if (data == NULL) return -1; memset(&di, 0, sizeof(di)); ret = rsa->meth->rsa_pub_dec(siglen, sigbuf, data, rsa, RSA_PKCS1_PADDING); if (ret <= 0) { free(data); return -2; } ret2 = decode_DigestInfo(data, ret, &di, &size); free(data); if (ret2 != 0) return -3; if (ret != size) { free_DigestInfo(&di); return -4; } if (flen != di.digest.length || memcmp(di.digest.data, from, flen) != 0) { free_DigestInfo(&di); return -5; } if (type == NID_sha1) { digest_alg = &_signature_sha1_data; } else if (type == NID_md5) { digest_alg = &_signature_md5_data; } else if (type == NID_sha256) { digest_alg = &_signature_sha256_data; } else { free_DigestInfo(&di); return -1; } ret = der_heim_oid_cmp(&digest_alg->algorithm, &di.digestAlgorithm.algorithm); free_DigestInfo(&di); if (ret != 0) return 0; return 1; } return 0; }
int rsautl_main(int argc, char **argv) { ENGINE *e = NULL; BIO *in = NULL, *out = NULL; char *infile = NULL, *outfile = NULL; #ifndef OPENSSL_NO_ENGINE char *engine = NULL; #endif char *keyfile = NULL; char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY; int keyform = FORMAT_PEM; char need_priv = 0, badarg = 0, rev = 0; char hexdump = 0, asn1parse = 0; X509 *x; EVP_PKEY *pkey = NULL; RSA *rsa = NULL; unsigned char *rsa_in = NULL, *rsa_out = NULL, pad; char *passargin = NULL, *passin = NULL; int rsa_inlen, rsa_outlen = 0; int keysize; int ret = 1; argc--; argv++; ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); pad = RSA_PKCS1_PADDING; while (argc >= 1) { if (!strcmp(*argv, "-in")) { if (--argc < 1) badarg = 1; else infile = *(++argv); } else if (!strcmp(*argv, "-out")) { if (--argc < 1) badarg = 1; else outfile = *(++argv); } else if (!strcmp(*argv, "-inkey")) { if (--argc < 1) badarg = 1; else keyfile = *(++argv); } else if (!strcmp(*argv, "-passin")) { if (--argc < 1) badarg = 1; else passargin = *(++argv); } else if (strcmp(*argv, "-keyform") == 0) { if (--argc < 1) badarg = 1; else keyform = str2fmt(*(++argv)); #ifndef OPENSSL_NO_ENGINE } else if (!strcmp(*argv, "-engine")) { if (--argc < 1) badarg = 1; else engine = *(++argv); #endif } else if (!strcmp(*argv, "-pubin")) { key_type = KEY_PUBKEY; } else if (!strcmp(*argv, "-certin")) { key_type = KEY_CERT; } else if (!strcmp(*argv, "-asn1parse")) asn1parse = 1; else if (!strcmp(*argv, "-hexdump")) hexdump = 1; else if (!strcmp(*argv, "-raw")) pad = RSA_NO_PADDING; else if (!strcmp(*argv, "-oaep")) pad = RSA_PKCS1_OAEP_PADDING; else if (!strcmp(*argv, "-ssl")) pad = RSA_SSLV23_PADDING; else if (!strcmp(*argv, "-pkcs")) pad = RSA_PKCS1_PADDING; else if (!strcmp(*argv, "-x931")) pad = RSA_X931_PADDING; else if (!strcmp(*argv, "-sign")) { rsa_mode = RSA_SIGN; need_priv = 1; } else if (!strcmp(*argv, "-verify")) rsa_mode = RSA_VERIFY; else if (!strcmp(*argv, "-rev")) rev = 1; else if (!strcmp(*argv, "-encrypt")) rsa_mode = RSA_ENCRYPT; else if (!strcmp(*argv, "-decrypt")) { rsa_mode = RSA_DECRYPT; need_priv = 1; } else badarg = 1; if (badarg) { usage(); goto end; } argc--; argv++; } if (need_priv && (key_type != KEY_PRIVKEY)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); goto end; } #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); #endif if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } switch (key_type) { case KEY_PRIVKEY: pkey = load_key(bio_err, keyfile, keyform, 0, passin, e, "Private Key"); break; case KEY_PUBKEY: pkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL, e, "Public Key"); break; case KEY_CERT: x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate"); if (x) { pkey = X509_get_pubkey(x); X509_free(x); } break; } if (!pkey) { return 1; } rsa = EVP_PKEY_get1_RSA(pkey); EVP_PKEY_free(pkey); if (!rsa) { BIO_printf(bio_err, "Error getting RSA key\n"); ERR_print_errors(bio_err); goto end; } if (infile) { if (!(in = BIO_new_file(infile, "rb"))) { BIO_printf(bio_err, "Error Reading Input File\n"); ERR_print_errors(bio_err); goto end; } } else in = BIO_new_fp(stdin, BIO_NOCLOSE); if (outfile) { if (!(out = BIO_new_file(outfile, "wb"))) { BIO_printf(bio_err, "Error Reading Output File\n"); ERR_print_errors(bio_err); goto end; } } else { out = BIO_new_fp(stdout, BIO_NOCLOSE); } keysize = RSA_size(rsa); rsa_in = reallocarray(NULL, keysize, 2); rsa_out = malloc(keysize); /* Read the input data */ rsa_inlen = BIO_read(in, rsa_in, keysize * 2); if (rsa_inlen <= 0) { BIO_printf(bio_err, "Error reading input Data\n"); exit(1); } if (rev) { int i; unsigned char ctmp; for (i = 0; i < rsa_inlen / 2; i++) { ctmp = rsa_in[i]; rsa_in[i] = rsa_in[rsa_inlen - 1 - i]; rsa_in[rsa_inlen - 1 - i] = ctmp; } } switch (rsa_mode) { case RSA_VERIFY: rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); break; case RSA_SIGN: rsa_outlen = RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); break; case RSA_ENCRYPT: rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); break; case RSA_DECRYPT: rsa_outlen = RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); break; } if (rsa_outlen <= 0) { BIO_printf(bio_err, "RSA operation error\n"); ERR_print_errors(bio_err); goto end; } ret = 0; if (asn1parse) { if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) { ERR_print_errors(bio_err); } } else if (hexdump) BIO_dump(out, (char *) rsa_out, rsa_outlen); else BIO_write(out, rsa_out, rsa_outlen); end: RSA_free(rsa); BIO_free(in); BIO_free_all(out); free(rsa_in); free(rsa_out); free(passin); return ret; }
int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding) { if (rsa->n == NULL || rsa->e == NULL) { OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); return 0; } const unsigned rsa_size = RSA_size(rsa); BIGNUM *f, *result; if (max_out < rsa_size) { OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL); return 0; } if (in_len != rsa_size) { OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN); return 0; } if (!check_modulus_and_exponent_sizes(rsa)) { return 0; } BN_CTX *ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } int ret = 0; uint8_t *buf = NULL; BN_CTX_start(ctx); f = BN_CTX_get(ctx); result = BN_CTX_get(ctx); if (f == NULL || result == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } if (padding == RSA_NO_PADDING) { buf = out; } else { // Allocate a temporary buffer to hold the padded plaintext. buf = OPENSSL_malloc(rsa_size); if (buf == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } } if (BN_bin2bn(in, in_len, f) == NULL) { goto err; } if (BN_ucmp(f, rsa->n) >= 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); goto err; } if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) || !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) { goto err; } if (!BN_bn2bin_padded(buf, rsa_size, result)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } switch (padding) { case RSA_PKCS1_PADDING: ret = RSA_padding_check_PKCS1_type_1(out, out_len, rsa_size, buf, rsa_size); break; case RSA_NO_PADDING: ret = 1; *out_len = rsa_size; break; default: OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); goto err; } if (!ret) { OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED); goto err; } err: BN_CTX_end(ctx); BN_CTX_free(ctx); if (buf != out) { OPENSSL_free(buf); } return ret; }
int bdd_search_modele ( MYSQL_RES* resultat_req, Ref* modele ) { // Initialisation Ref reference ; int return_value ; int suite = TRUE ; MYSQL_ROW tuple ; char* user = NULL ; char* safe_tuple = NULL ; // Permet d'appeler strtok_r sur le bon contenu. char* reponse = NULL ; int first = TRUE ; // Initialisation user = (char*) malloc ( TAILLE_HASH_NOM * sizeof ( char ) ) ; memset ( user, '\0', TAILLE_HASH_NOM ) ; // Initialisation char* output = (char*) malloc ( RSA_size ( bdd_key ) * sizeof ( char ) ) ; memset ( output, '\0', RSA_size ( bdd_key ) ) ; // Initialisation char* temporaire = (char*) malloc ( ( TAILLE_MAX_REF + TAILLE_HASH_NOM + 3 ) * nbr_tuples * sizeof ( char ) ) ; memset ( temporaire, '\0', ( TAILLE_MAX_REF + TAILLE_HASH_NOM + 3 ) * nbr_tuples ) ; // On parcourt chaque tuple while ( suite == TRUE ) { // On récupère un tuple if ( ( tuple = mysql_fetch_row ( resultat_req ) ) == NULL ) suite = FALSE ; // On le traite if ( suite == TRUE ) { // On découpe la référence if ( ( return_value = ref_split ( tuple[0], &reference ) ) == ERRNO ) { perror ( "Erreur_bdd_search_modele : ref_split " ) ; free ( user ) ; free ( output ) ; bdd_send_msg ( SEEK, "ERROR" ) ; return ERRNO ; } // On regarde si elle correspond à ce que l'on recherche if ( ( return_value = ref_cmp ( &reference, modele ) ) == ERRNO ) { perror ( "Erreur_bdd_traitement_request : ref_cmp " ) ; free ( user ) ; free ( output ) ; bdd_send_msg ( SEEK, "ERROR" ) ; return ERRNO ; } else if ( return_value == TRUE ) // La référence nous intéresse { // On déchiffre le tuple memset ( output, '\0', RSA_size ( bdd_key ) ) ; if ( RSA_chiffrement ( (unsigned char*) tuple[1], (unsigned char*) output, DECHIFFREMENT ) != TRUE ) { perror ( "Erreur_bdd_serach_modele : RSA_dechiffrement " ) ; free ( output ) ; free ( user ) ; bdd_send_msg ( SEEK, "ERROR" ) ; return ERRNO ; } // On récupère le hash du nom associé memset ( user, '\0', TAILLE_HASH_NOM ) ; sprintf ( user, "%s", strtok_r ( output, "*", &safe_tuple ) ) ; // On ajoute la référence et le nom associé à la réponse if ( first == TRUE ) { sprintf ( temporaire, "%s;%s", tuple[0], user ) ; first = FALSE ; } else if ( first == FALSE ) sprintf ( temporaire + strlen ( temporaire ), "*%s;%s", tuple[0], user ) ; } } } // On envoie la réponse int taille = strlen ( temporaire ) + 10 ; reponse = (char*) malloc ( taille * sizeof ( char ) ) ; memset ( reponse, '\0', taille ) ; sprintf ( reponse, "%d*%s*EOF", SEEK, temporaire ) ; res_send ( reponse ) ; // Free free ( output ) ; free ( user ) ; free ( temporaire ) ; free ( reponse ) ; // On indique que tout s'est bien déroulé return TRUE ; }
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; } } else if (dtype == NID_md5_sha1) { /* Special case: SSL signature */ 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); }
int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding) { const unsigned rsa_size = RSA_size(rsa); int r = -1; uint8_t *buf = NULL; int ret = 0; if (max_out < rsa_size) { OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL); return 0; } if (padding == RSA_NO_PADDING) { buf = out; } else { /* Allocate a temporary buffer to hold the padded plaintext. */ buf = OPENSSL_malloc(rsa_size); if (buf == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } } if (in_len != rsa_size) { OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN); goto err; } if (!RSA_private_transform(rsa, buf, in, rsa_size)) { goto err; } switch (padding) { case RSA_PKCS1_PADDING: r = RSA_padding_check_PKCS1_type_2(out, rsa_size, buf, rsa_size); break; case RSA_PKCS1_OAEP_PADDING: /* Use the default parameters: SHA-1 for both hashes and no label. */ r = RSA_padding_check_PKCS1_OAEP_mgf1(out, rsa_size, buf, rsa_size, NULL, 0, NULL, NULL); break; case RSA_NO_PADDING: r = rsa_size; break; default: OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); goto err; } if (r < 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED); } else { *out_len = r; ret = 1; } err: if (padding != RSA_NO_PADDING && buf != NULL) { OPENSSL_cleanse(buf, rsa_size); OPENSSL_free(buf); } return ret; }
int RSA_sign(int type, const unsigned char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, RSA *rsa) { X509_SIG sig; ASN1_TYPE parameter; int i, j, ret = 1; unsigned char *p, *tmps = NULL; const unsigned char *s = NULL; X509_ALGOR algor; ASN1_OCTET_STRING digest; if (rsa->meth->rsa_sign) { return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa); } /* Special case: SSL signature, just check the length */ if (type == NID_md5_sha1) { if (m_len != SSL_SIG_LENGTH) { RSAerr(RSA_F_RSA_SIGN, RSA_R_INVALID_MESSAGE_LENGTH); return (0); } i = SSL_SIG_LENGTH; s = m; } else { sig.algor = &algor; sig.algor->algorithm = OBJ_nid2obj(type); if (sig.algor->algorithm == NULL) { RSAerr(RSA_F_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE); return (0); } if (OBJ_length(sig.algor->algorithm) == 0) { RSAerr(RSA_F_RSA_SIGN, RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); return (0); } parameter.type = V_ASN1_NULL; parameter.value.ptr = NULL; sig.algor->parameter = ¶meter; sig.digest = &digest; sig.digest->data = (unsigned char *)m; /* TMP UGLY CAST */ sig.digest->length = m_len; i = i2d_X509_SIG(&sig, NULL); } j = RSA_size(rsa); if (i > (j - RSA_PKCS1_PADDING_SIZE)) { RSAerr(RSA_F_RSA_SIGN, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY); return (0); } if (type != NID_md5_sha1) { tmps = OPENSSL_malloc((unsigned int)j + 1); if (tmps == NULL) { RSAerr(RSA_F_RSA_SIGN, ERR_R_MALLOC_FAILURE); return (0); } p = tmps; i2d_X509_SIG(&sig, &p); s = tmps; } i = RSA_private_encrypt(i, s, sigret, rsa, RSA_PKCS1_PADDING); if (i <= 0) ret = 0; else *siglen = i; if (type != NID_md5_sha1) OPENSSL_clear_free(tmps, (unsigned int)j + 1); return (ret); }
int rsa_default_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding) { const unsigned rsa_size = RSA_size(rsa); BIGNUM *f, *result; uint8_t *buf = NULL; BN_CTX *ctx = NULL; int i, ret = 0; if (max_out < rsa_size) { OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL); return 0; } if (!check_modulus_and_exponent_sizes(rsa)) { return 0; } ctx = BN_CTX_new(); if (ctx == NULL) { goto err; } BN_CTX_start(ctx); f = BN_CTX_get(ctx); result = BN_CTX_get(ctx); buf = OPENSSL_malloc(rsa_size); if (!f || !result || !buf) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } switch (padding) { case RSA_PKCS1_PADDING: i = RSA_padding_add_PKCS1_type_2(buf, rsa_size, in, in_len); break; case RSA_PKCS1_OAEP_PADDING: /* Use the default parameters: SHA-1 for both hashes and no label. */ i = RSA_padding_add_PKCS1_OAEP_mgf1(buf, rsa_size, in, in_len, NULL, 0, NULL, NULL); break; case RSA_NO_PADDING: i = RSA_padding_add_none(buf, rsa_size, in, in_len); break; default: OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); goto err; } if (i <= 0) { goto err; } if (BN_bin2bn(buf, rsa_size, f) == NULL) { goto err; } if (BN_ucmp(f, rsa->n) >= 0) { /* usually the padding functions would catch this */ OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; } if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) { if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) == NULL) { goto err; } } if (!rsa->meth->bn_mod_exp(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) { goto err; } /* put in leading 0 bytes if the number is less than the length of the * modulus */ if (!BN_bn2bin_padded(out, rsa_size, result)) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); goto err; } *out_len = rsa_size; ret = 1; err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (buf != NULL) { OPENSSL_cleanse(buf, rsa_size); OPENSSL_free(buf); } return ret; }
int main(int argc, char **argv) { if(argc != 5) usageError(); struct addrinfo hints, *res, *p; int sock, gai; FILE *s; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; // use tcp socket hints.ai_family = PF_UNSPEC; // use ipv4 or ipv6 hints.ai_flags = AI_ADDRCONFIG; // use ipv6 if we have interface printf("Connecting to %s:%s ...\n", argv[3], argv[4]); if(0 != (gai = getaddrinfo(argv[3], argv[4], &hints, &res))) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(gai)); exit(EXIT_FAILURE); } /* as no domain was specified, use both (v4/v6) and check which connects properly */ for(p = res; p != NULL; p = p->ai_next) { sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if(0 == connect(sock, p->ai_addr, p->ai_addrlen)) break; } if(NULL == p) { perror("socket"); exit(EXIT_FAILURE); } #ifdef DEBUG printf("Domain: %d; Type: %d; Protocol: %d\n", p->ai_family, p->ai_socktype, p->ai_protocol); #endif /* open network stream for conveniente read/write */ if(NULL == (s = fdopen(sock, "a+"))) { perror("fdopen"); exit(EXIT_FAILURE); } printf("Connection established\n"); /* init crypto */ ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); FILE *privKey, *pubKey; RSA *rsaPrivKey = NULL; RSA *rsaPubKey = NULL; int encSize, decSize, encSizeToServer; /* open and read client private key */ if(NULL == (privKey = fopen(argv[1], "r"))) { perror("fopen"); exit(EXIT_FAILURE); } if(NULL == (rsaPrivKey = PEM_read_RSAPrivateKey(privKey,NULL, NULL, CLIENTPASSPHRASE))) { fprintf(stderr, "PEM_read_RSAPrivateKey: %s\n", ERR_error_string(ERR_get_error(), NULL)); exit(EXIT_FAILURE); } encSize = RSA_size(rsaPrivKey); decSize = RSA_size(rsaPrivKey) - RSA_PKCS1_OAEP_PADDING_SIZE; unsigned char decChallenge[decSize]; unsigned char encChallenge[encSize]; /* get the encrypted challenge from server */ fread(encChallenge, encSize, 1, s); #ifdef DEBUG printf("encrypted Challenge received:\n"); dump(encChallenge, encSize); #endif /* decrypted challenge from server */ if(0 == RSA_private_decrypt(encSize, encChallenge, decChallenge, rsaPrivKey, RSA_PKCS1_OAEP_PADDING)) { fprintf(stderr, "RSA_public_decrypt: %s\n", ERR_error_string(ERR_get_error(), NULL)); exit(EXIT_FAILURE); } unsigned char challenge[decSize]; memcpy(challenge, decChallenge, decSize); // save the decrypted challenge for later /* encrypting answer to server */ /* open server public Key */ if(NULL == (pubKey = fopen(argv[2], "r"))) { perror("fopen"); exit(EXIT_FAILURE); } if(NULL == (rsaPubKey = PEM_read_RSA_PUBKEY(pubKey, NULL, NULL, NULL))) { perror("PEM_read_RSA_PUBKEY"); exit(EXIT_FAILURE); } encSizeToServer = RSA_size(rsaPubKey); unsigned char encChallengeToServer[encSizeToServer]; /* encrypt the (decrypted) challenge again, now with server's publickey */ if(-1 == RSA_public_encrypt(decSize, decChallenge, encChallengeToServer, rsaPubKey, RSA_PKCS1_OAEP_PADDING)) { fprintf(stderr, "RSA_public_encrypt: %s\n", ERR_error_string(ERR_get_error(), NULL)); exit(EXIT_FAILURE); } #ifdef DEBUG printf("plaintext Challenge received:\n"); dump(decChallenge, decSize); printf("encrypted Challenge to Server:\n"); dump(encChallengeToServer, encSizeToServer); #endif /* send encrypted challenge to server */ fwrite(encChallengeToServer, encSizeToServer,1, s); /*----------------------------------------------------------------------------- * Challenge Response finished * Attention: there is no (client) verification if chall/resp has successfully finished * in case of failure, client will get stuck... * * continuing with AES * IV consisting of 1/2 of the Challenge * KEY consisting of the other half *-----------------------------------------------------------------------------*/ EVP_CIPHER_CTX cctx; EVP_CIPHER_CTX_init(&cctx); int keylen = decSize/2; unsigned char key[keylen]; unsigned char iv[keylen]; memcpy(key, challenge, keylen); memcpy(iv, challenge+keylen, keylen); /* init AES decrypt context */ if(0 == EVP_CipherInit_ex(&cctx, EVP_aes_256_ofb(), NULL, key, iv, 0)){ perror("EVP_CipherInit_ex"); exit(EXIT_FAILURE); } unsigned char *decBuf = (unsigned char*) malloc(AESBUFFSIZE); unsigned char *encBuf = (unsigned char*) malloc(AESBUFFSIZE); /* get the "Hello from server!" message */ fread(encBuf, AESBUFFSIZE, 1, s); printf("Authentication successfull\n"); int bufLen = AESBUFFSIZE; /* decrypt the message */ if(0 == EVP_CipherUpdate(&cctx, decBuf, &bufLen, encBuf, bufLen)) { EVP_CIPHER_CTX_cleanup(&cctx); perror("EVP_CipherUpdate"); exit(EXIT_FAILURE); } EVP_CIPHER_CTX_cleanup(&cctx); printf("Received AES message: %s\n", decBuf); /* init AES encrypt context */ bufLen = AESBUFFSIZE; if(0 == EVP_CipherInit_ex(&cctx, EVP_aes_256_ofb(), NULL, key, iv, 1)){ perror("EVP_CipherInit_ex"); exit(EXIT_FAILURE); } /* restore all buffers */ bufLen = AESBUFFSIZE; decBuf = (unsigned char*) malloc(AESBUFFSIZE); encBuf = (unsigned char*) malloc(AESBUFFSIZE); /* encrypt and send the client -> server message */ decBuf = (unsigned char*) "Hello from client."; if(0 == EVP_CipherUpdate(&cctx, encBuf, &bufLen, decBuf, bufLen)) { EVP_CIPHER_CTX_cleanup(&cctx); perror("EVP_CipherUpdate"); exit(EXIT_FAILURE); } printf("Send AES message: %s\n", decBuf); fwrite(encBuf, bufLen, 1, s); /* sending/receiving could continue here */ /* cleanup */ EVP_CIPHER_CTX_cleanup(&cctx); fclose(s); freeaddrinfo(res); printf("Connection closed.\n"); return 0; }
static int int_rsa_size(const EVP_PKEY *pkey) { return RSA_size(pkey->pkey.rsa); }
static bool _cjose_jws_build_sig_rs(cjose_jws_t *jws, const cjose_jwk_t *jwk, cjose_err *err) { // ensure jwk is private RSA if (jwk->kty != CJOSE_JWK_KTY_RSA) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); return false; } RSA *rsa = (RSA *)jwk->keydata; BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; _cjose_jwk_rsa_get(rsa, &rsa_n, &rsa_e, &rsa_d); if (!rsa || !rsa_e || !rsa_n || !rsa_d) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); return false; } // allocate buffer for signature jws->sig_len = RSA_size((RSA *)jwk->keydata); jws->sig = (uint8_t *)cjose_get_alloc()(jws->sig_len); if (NULL == jws->sig) { CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY); return false; } // make sure we have an alg header json_t *alg_obj = json_object_get(jws->hdr, CJOSE_HDR_ALG); if (NULL == alg_obj) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); return false; } const char *alg = json_string_value(alg_obj); // build digest using SHA-256/384/512 digest algorithm int digest_alg = -1; if (strcmp(alg, CJOSE_HDR_ALG_RS256) == 0) digest_alg = NID_sha256; else if (strcmp(alg, CJOSE_HDR_ALG_RS384) == 0) digest_alg = NID_sha384; else if (strcmp(alg, CJOSE_HDR_ALG_RS512) == 0) digest_alg = NID_sha512; if (-1 == digest_alg) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); return false; } unsigned int siglen; if (RSA_sign(digest_alg, jws->dig, jws->dig_len, jws->sig, &siglen, (RSA *)jwk->keydata) != 1) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); return false; } jws->sig_len = siglen; // base64url encode signed digest if (!cjose_base64url_encode((const uint8_t *)jws->sig, jws->sig_len, &jws->sig_b64u, &jws->sig_b64u_len, err)) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); return false; } return true; }