Beispiel #1
0
int main(int argc, char *argv[])
{
    int err = 0;
    int v;
    RSA *key;
    unsigned char ptext[256];
    unsigned char ctext[256];
    static unsigned char ptext_ex[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a";
    unsigned char ctext_ex[256];
    int plen;
    int clen = 0;
    int num;
    int n;

    CRYPTO_set_mem_debug(1);
    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

    RAND_seed(rnd_seed, sizeof rnd_seed); /* or OAEP may fail */

    plen = sizeof(ptext_ex) - 1;

    for (v = 0; v < 6; v++) {
        key = RSA_new();
        switch (v % 3) {
        case 0:
            clen = key1(key, ctext_ex);
            break;
        case 1:
            clen = key2(key, ctext_ex);
            break;
        case 2:
            clen = key3(key, ctext_ex);
            break;
        }
        if (v / 3 >= 1)
            RSA_set_flags(key, RSA_FLAG_NO_CONSTTIME);

        num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
                                 RSA_PKCS1_PADDING);
        if (num != clen) {
            printf("PKCS#1 v1.5 encryption failed!\n");
            err = 1;
            goto oaep;
        }

        num = RSA_private_decrypt(num, ctext, ptext, key, RSA_PKCS1_PADDING);
        if (num != plen || memcmp(ptext, ptext_ex, num) != 0) {
            printf("PKCS#1 v1.5 decryption failed!\n");
            err = 1;
        } else
            printf("PKCS #1 v1.5 encryption/decryption ok\n");

 oaep:
        ERR_clear_error();
        num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
                                 RSA_PKCS1_OAEP_PADDING);
        if (num == -1 && pad_unknown()) {
            printf("No OAEP support\n");
            goto next;
        }
        if (num != clen) {
            printf("OAEP encryption failed!\n");
            err = 1;
            goto next;
        }

        num = RSA_private_decrypt(num, ctext, ptext, key,
                                  RSA_PKCS1_OAEP_PADDING);
        if (num != plen || memcmp(ptext, ptext_ex, num) != 0) {
            printf("OAEP decryption (encrypted data) failed!\n");
            err = 1;
        } else if (memcmp(ctext, ctext_ex, num) == 0)
            printf("OAEP test vector %d passed!\n", v);

        /*
         * Different ciphertexts (rsa_oaep.c without -DPKCS_TESTVECT). Try
         * decrypting ctext_ex
         */

        num = RSA_private_decrypt(clen, ctext_ex, ptext, key,
                                  RSA_PKCS1_OAEP_PADDING);

        if (num != plen || memcmp(ptext, ptext_ex, num) != 0) {
            printf("OAEP decryption (test vector data) failed!\n");
            err = 1;
        } else
            printf("OAEP encryption/decryption ok\n");

        /* Try decrypting corrupted ciphertexts. */
        for (n = 0; n < clen; ++n) {
            ctext[n] ^= 1;
            num = RSA_private_decrypt(clen, ctext, ptext, key,
                                          RSA_PKCS1_OAEP_PADDING);
            if (num > 0) {
                printf("Corrupt data decrypted!\n");
                err = 1;
                break;
            }
            ctext[n] ^= 1;
        }

        /* Test truncated ciphertexts, as well as negative length. */
        for (n = -1; n < clen; ++n) {
            num = RSA_private_decrypt(n, ctext, ptext, key,
                                      RSA_PKCS1_OAEP_PADDING);
            if (num > 0) {
                printf("Truncated data decrypted!\n");
                err = 1;
                break;
            }
        }

 next:
        RSA_free(key);
    }

#ifndef OPENSSL_NO_CRYPTO_MDEBUG
    if (CRYPTO_mem_leaks_fp(stderr) <= 0)
        err = 1;
#endif

    return err;
}
Beispiel #2
0
int 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++;

    if (!bio_err)
        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);

    if (!load_config(bio_err, NULL))
        goto end;
    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;
    }

/* FIXME: seed PRNG only if needed */
    app_RAND_load_file(NULL, bio_err, 0);

    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);
# ifdef OPENSSL_SYS_VMS
        {
            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
            out = BIO_push(tmpbio, out);
        }
# endif
    }

    keysize = RSA_size(rsa);

    rsa_in = OPENSSL_malloc(keysize * 2);
    rsa_out = OPENSSL_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);
    if (rsa_in)
        OPENSSL_free(rsa_in);
    if (rsa_out)
        OPENSSL_free(rsa_out);
    if (passin)
        OPENSSL_free(passin);
    return ret;
}
Beispiel #3
0
/**
 * crypto_rsa_decrypt(key, data, len, out, outlen):
 * Decrypt the provided data with the specified key, writing the ciphertext
 * into ${out} (of length ${outlen}).  Set ${*outlen} to the length of the
 * plaintext, and return 0 on success, 1 if the ciphertext is invalid, or
 * -1 on error.
 */
int
crypto_rsa_decrypt(int key, const uint8_t * data, size_t len,
    uint8_t * out, size_t * outlen)
{
	RSA * rsa;
	uint8_t EM[256];
	uint8_t lHash[32];
	uint8_t baddata, paddingmask;
	uint8_t maskedSeed[32];
	uint8_t maskedDB[223];
	uint8_t seedMask[32];
	uint8_t seed[32];
	uint8_t dbMask[223];
	uint8_t DB[223];
	size_t msglen;
	size_t i;
	unsigned long rsaerr;

	/* Sanity check. */
	assert(len < INT_MAX);

	/* Find the required key. */
	if ((rsa = crypto_keys_lookup_RSA(key)) == NULL)
		goto err0;

	/* Make sure the key and ciphertext buffer are the correct size. */
	if (!crypto_compat_RSA_valid_size(rsa)) {
		warn0("RSA key is incorrect size");
		goto err0;
	}
	if (len != 256) {
		warn0("Programmer error: "
		    "ciphertext buffer is incorrect length");
		goto err0;
	}

	/* Make sure the plaintext buffer is large enough. */
	if (*outlen < 256) {
		warn0("Programmer error: "
		    "plaintext buffer is too small");
		goto err0;
	}

	/* Convert the ciphertext to EM, via RSA. */
	if (RSA_private_decrypt((int)len, data, EM, rsa, RSA_NO_PADDING)
	    != 256) {
		/*
		 * We can only distinguish between bad ciphertext and an
		 * internal error in OpenSSL by looking at the error code.
		 */
		rsaerr = ERR_get_error();
		if (rsaerr == RSA_R_DATA_TOO_LARGE_FOR_MODULUS)
			goto bad;

		/* Anything else is an internal error in OpenSSL. */
		warn0("%s", ERR_error_string(rsaerr, NULL));
		goto err0;
	}

	/* Construct lHash as specified in RSAES-OAEP-DECRYPT in RFC 3447. */
	if (crypto_hash_data(CRYPTO_KEY_HMAC_SHA256, NULL, 0, lHash)) {
		warn0("Programmer error: "
		    "SHA256 should never fail");
		goto err0;
	}

	/*
	 * The high byte of EM must be zero.  We test this later to avoid
	 * timing side channel attacks.
	 */
	baddata = EM[0];

	/* Construct maskedSeed and maskedDB. */
	memcpy(maskedSeed, EM + 1, 32);
	memcpy(maskedDB, EM + 33, 223);

	/* Construct seedMask and seed. */
	crypto_MGF1(maskedDB, 223, seedMask, 32);
	for (i = 0; i < 32; i++)
		seed[i] = maskedSeed[i] ^ seedMask[i];

	/* Construct dbMask and DB. */
	crypto_MGF1(seed, 32, dbMask, 223);
	for (i = 0; i < 223; i++)
		DB[i] = maskedDB[i] ^ dbMask[i];

	/*
	 * The leading 32 bytes of DB must be equal to lHash.  Test them all
	 * at once, simultaneous with other tests, in order to avoid timing
	 * side channel attacks.
	 */
	baddata = baddata | crypto_verify_bytes(DB, lHash, 32);

	/*
	 * Bytes 33 -- 223 of DB must be zero bytes followed by a one byte
	 * followed by the real data.  The following code will set baddata
	 * to a non-zero value if there are non-{0, 1} bytes which are not
	 * separated from the start by a 1 byte.
	 */
	paddingmask = 0xff;
	msglen = 191;
	for (i = 32; i < 223; i++) {
		/* If we're still doing padding, DB[i] should be 0 or 1. */
		baddata = baddata | (paddingmask & DB[i] & 0xfe);

		/*
		 * If baddata is still 0, paddingmask is either 0xff or 0x00
		 * depending upon whether the current byte is padding or not.
		 * Treating it as a signed integer and adding it to msglen
		 * will result in msglen holding the length of the message
		 * after the padding is removed.
		 */
		msglen += (size_t)((int8_t)(paddingmask));

		/*-
		 * If baddata is still 0, there are 3 cases:
		 * 1. We're no longer looking at padding, and paddingmask is
		 *    0x00, so &ing it with something won't change it.
		 * 2. We're looking at a 0 byte of padding, paddingmask is
		 *    0xff, and we want it to remain 0xff.
		 * 3. We're looking at a 1 byte of padding, paddingmask is
		 *    0xff, and we want it to become 0x00.
		 * In all three cases, &ing the byte minus one does what we
		 * want.
		 */
		paddingmask = paddingmask & (DB[i] - 1);
	}

	/* Once we hit the end, the padding should be over. */
	baddata = baddata | paddingmask;

	/* Is the data bad? */
	if (baddata)
		goto bad;

	/* Sanity check the message length. */
	if (msglen > *outlen) {
		warn0("Programmer error: "
		    "decrypted message length is insane");
		goto err0;
	}

	/* Copy the message into the output buffer. */
	memcpy(out, DB + 223 - msglen, msglen);
	*outlen = msglen;

	/* Success! */
	return (0);

bad:
	/* Bad signature. */
	return (1);

err0:
	/* Failure! */
	return (-1);
}
Beispiel #4
0
int main(void)
{
    int     i;
	BIO*    bio_out;

    RSA*    public_key          = NULL;
    RSA*    private_key         = NULL;
    BIGNUM* public_key_exponent = NULL;
    RSA*    key_pair            = NULL;

    int     ciphertext_len      = 0;
    int     plaintext_len       = 0;
    unsigned char*  ciphertext  = NULL;
    unsigned char*  plaintext   = NULL;


    unsigned char   seed_data[SEED_SIZE];

    /* The data to encrypt. The data, in ASCII form is: "Test Data!" */
    unsigned char data[]  = "\x54\x65\x73\x74\x20\x44\x61\x74\x61\x21";

    /* Length of the above data. For PKCS #1 v1.5, this length must be 11 bytes less than the size of the modulus */
    int data_length       = sizeof(data) - 1;

    /* Before generating the keys, the pseudo-random number generator must be seeded */
    generate_seed(seed_data, SEED_SIZE);
    RAND_seed(seed_data, SEED_SIZE);

    /* Generate a 2048-bit key pair with a public exponent of 65537 (RSA_F4) */
    public_key_exponent = BN_new();
    key_pair            = RSA_new();

    BN_set_word(public_key_exponent, RSA_F4);
    RSA_generate_key_ex(key_pair, 2048, public_key_exponent, NULL);

    /*
        NOTE: In the following instance, we split the key-pair in to public and private keys.
              This is not necessary for this code to be functional. We do this because we don't
              want our private key information to be distributed with the public key.
    */

    public_key  = retrieve_public_key(key_pair);
    private_key = retrieve_private_key(key_pair);

    /* Retrieve the ciphertext length (i.e. size of the modulus) */
    ciphertext_len  = RSA_size(public_key);

    /* Allocate the required amount of memory for the ciphertext. */
    ciphertext      = (unsigned char*) calloc(ciphertext_len, sizeof(unsigned char));    
    
    /* Carry out the encryption */
    if ((ciphertext_len = RSA_public_encrypt(data_length, data, ciphertext, public_key, RSA_PKCS1_OAEP_PADDING)) == -1)
    {        
        fprintf(stderr, "Error carrying out encryption. Error code: %lu\n", ERR_get_error());
        exit(1);
    }

    /* Setup output */
    bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);

    BIO_printf(bio_out, "Original plaintext: %s\n\n", data);
    BIO_printf(bio_out, "Ciphertext: ");


    /* Print out the ciphertext */
    for (i = 0; i < ciphertext_len; i++)
        BIO_printf(bio_out, "%02x", ((unsigned char*)ciphertext)[i]);

    BIO_printf(bio_out, "\n\n");


    /* Start the decryption process */

    /* Allocate the same amount of memory (as for the ciphertext) for the plaintext. */
    plaintext   = (unsigned char*) calloc(ciphertext_len, sizeof(unsigned char)); 

    /* Now, carry out the decryption */ 
    if ((plaintext_len = RSA_private_decrypt(ciphertext_len, ciphertext, plaintext, private_key, RSA_PKCS1_OAEP_PADDING)) == -1)
    {
        fprintf(stderr, "Error carrying out the decryption. Error code: %lu\n", ERR_get_error());
        exit(1);
    }
        
    BIO_printf(bio_out, "Recovered plaintext: ");    

    /* Print out the plaintext. Note: We use the length returned by RSA_private_decrypt */
    for (i = 0; i < plaintext_len; i++)
        BIO_printf(bio_out, "%c", ((unsigned char*)plaintext)[i]);

    BIO_printf(bio_out, "\n\n");


    free(ciphertext);
    free(plaintext);

    BIO_free(bio_out);

    RSA_free(public_key);
    RSA_free(private_key);
    RSA_free(key_pair);

    return 0;
}
Beispiel #5
0
QString AuthorizationManager::decryptString(QString str, QByteArray key){
  bool pub=true;
  if(key.contains(" PUBLIC KEY--")){ pub=true; }
  else if(key.contains(" PRIVATE KEY--")){ pub=false; }
  else{  //unknown encryption - just return as-is
    if(!key.isEmpty()){ qDebug() << "Unknown key type!!" << key; } 
    return str; 
  }
  //Convert the input string into block elements as needed (and decode base64);
  QList<QByteArray> blocks;
  //QJsonDocument doc = QJsonDocument::fromJson(str.toLocal8Bit());
  //if(doc.isNull()){
    //No individual blocks - just one string
    QByteArray bytes; bytes.append(str);
    blocks << QByteArray::fromBase64(bytes);
  /*}else if(doc.isArray()){
    for(int i=0; i<doc.array().count(); i++){
      QByteArray bytes; bytes.append(doc.array()[i].toString());
      blocks << QByteArray::fromBase64(bytes);
    }
  }else{
    //Already valid JSON - return it
    return str;
  }*/
  //qDebug() << "Decoded String:" << bytes;
  return QString(blocks.join()); //TEMPORARY BYPASS

   //qDebug() << "Start decoding String:" << pub << str;//<< key;
  //Reset/Load some SSL stuff
    //OpenSSL_add_all_algorithms();
    //ERR_load_crypto_strings();

  QString outstring; //output string
  //unsigned char *decode = (unsigned char*)malloc(5*bytes.size());
  RSA *rsa= NULL;
  BIO *keybio = NULL;
  //qDebug() << " - Generate keybio";
  keybio = BIO_new_mem_buf(key.data(), -1);
  if(keybio==NULL){ return ""; }
  //qDebug() << " - Read pubkey";
  if(pub){
    //PUBLIC KEY
    rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
    if(rsa==NULL){ qDebug() << " - Invalid Public RSA key!!" <<  key; BIO_free_all(keybio); return ""; }
    //decode = (unsigned char*)malloc( RSA_size(rsa) );
    //qDebug() << " - Decrypt string";
    for(int i=0; i<blocks.length(); i++){
      unsigned char *decode = (unsigned char*)malloc(2*blocks[i].size());
      int len = RSA_public_decrypt(blocks[i].size(), (unsigned char*)(blocks[i].data()), decode, rsa, RSA_PKCS1_PADDING);
      if(len<0){ 
        qDebug() << " - Could not decrypt"; 
        qDebug() << ERR_error_string (ERR_peek_error(), NULL);
        qDebug() << ERR_error_string (ERR_peek_last_error(), NULL); 
        outstring.clear();
        break;
      }
      //qDebug() << " - done";
      outstring.append( QString( QByteArray( (char*)(decode), len) ) );
    }
    RSA_free(rsa);
    BIO_free_all(keybio);

  }else{
    //PRIVATE KEY
    rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
    if(rsa==NULL){ qDebug() << " - Invalid RSA key!!"; BIO_free_all(keybio); return ""; }
    //decode = (unsigned char*)malloc( RSA_size(rsa) );
    //qDebug() << " - Decrypt string";
    for(int i=0; i<blocks.length(); i++){
      unsigned char *decode = (unsigned char*)malloc(2*blocks[i].size());
      int len = RSA_private_decrypt(blocks[i].size(), (unsigned char*)(blocks[i].data()), decode, rsa, RSA_PKCS1_PADDING);
      if(len<0){ 
        qDebug() << " - Could not decrypt"; 
        qDebug() << ERR_error_string (ERR_peek_error(), NULL);
        qDebug() << ERR_error_string (ERR_peek_last_error(), NULL); 
        outstring.clear();
        break;
      }
      //qDebug() << " - done";
      outstring.append( QString( QByteArray( (char*)(decode), len) ) );
    }
    RSA_free(rsa);
    BIO_free_all(keybio);
  }
  return outstring;
}
Beispiel #6
0
static bool
decrypt(const char *privkeyfile, const char *keyfile, const char *input,
    const char *output)
{
	uint8_t buf[KERNELDUMP_BUFFER_SIZE], key[KERNELDUMP_KEY_MAX_SIZE];
	EVP_CIPHER_CTX ctx;
	const EVP_CIPHER *cipher;
	FILE *fp;
	struct kerneldumpkey *kdk;
	RSA *privkey;
	int ifd, kfd, ofd, olen, privkeysize;
	ssize_t bytes;
	pid_t pid;

	PJDLOG_ASSERT(privkeyfile != NULL);
	PJDLOG_ASSERT(keyfile != NULL);
	PJDLOG_ASSERT(input != NULL);
	PJDLOG_ASSERT(output != NULL);

	privkey = NULL;

	/*
	 * Decrypt a core dump in a child process so we can unlink a partially
	 * decrypted core if the child process fails.
	 */
	pid = fork();
	if (pid == -1) {
		pjdlog_errno(LOG_ERR, "Unable to create child process");
		return (false);
	}

	if (pid > 0)
		return (wait_for_process(pid) == 0);

	kfd = open(keyfile, O_RDONLY);
	if (kfd == -1) {
		pjdlog_errno(LOG_ERR, "Unable to open %s", keyfile);
		goto failed;
	}
	ifd = open(input, O_RDONLY);
	if (ifd == -1) {
		pjdlog_errno(LOG_ERR, "Unable to open %s", input);
		goto failed;
	}
	ofd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0600);
	if (ofd == -1) {
		pjdlog_errno(LOG_ERR, "Unable to open %s", output);
		goto failed;
	}
	fp = fopen(privkeyfile, "r");
	if (fp == NULL) {
		pjdlog_errno(LOG_ERR, "Unable to open %s", privkeyfile);
		goto failed;
	}

	if (cap_enter() < 0 && errno != ENOSYS) {
		pjdlog_errno(LOG_ERR, "Unable to enter capability mode");
		goto failed;
	}

	privkey = RSA_new();
	if (privkey == NULL) {
		pjdlog_error("Unable to allocate an RSA structure: %s",
		    ERR_error_string(ERR_get_error(), NULL));
		goto failed;
	}
	EVP_CIPHER_CTX_init(&ctx);

	kdk = read_key(kfd);
	close(kfd);
	if (kdk == NULL)
		goto failed;

	privkey = PEM_read_RSAPrivateKey(fp, &privkey, NULL, NULL);
	fclose(fp);
	if (privkey == NULL) {
		pjdlog_error("Unable to read data from %s.", privkeyfile);
		goto failed;
	}

	privkeysize = RSA_size(privkey);
	if (privkeysize != (int)kdk->kdk_encryptedkeysize) {
		pjdlog_error("RSA modulus size mismatch: equals %db and should be %ub.",
		    8 * privkeysize, 8 * kdk->kdk_encryptedkeysize);
		goto failed;
	}

	switch (kdk->kdk_encryption) {
	case KERNELDUMP_ENC_AES_256_CBC:
		cipher = EVP_aes_256_cbc();
		break;
	default:
		pjdlog_error("Invalid encryption algorithm.");
		goto failed;
	}

	if (RSA_private_decrypt(kdk->kdk_encryptedkeysize,
	    kdk->kdk_encryptedkey, key, privkey,
	    RSA_PKCS1_PADDING) != sizeof(key)) {
		pjdlog_error("Unable to decrypt key: %s",
		    ERR_error_string(ERR_get_error(), NULL));
		goto failed;
	}
	RSA_free(privkey);
	privkey = NULL;

	EVP_DecryptInit_ex(&ctx, cipher, NULL, key, kdk->kdk_iv);
	EVP_CIPHER_CTX_set_padding(&ctx, 0);

	explicit_bzero(key, sizeof(key));

	do {
		bytes = read(ifd, buf, sizeof(buf));
		if (bytes < 0) {
			pjdlog_errno(LOG_ERR, "Unable to read data from %s",
			    input);
			goto failed;
		} else if (bytes == 0) {
			break;
		}

		if (bytes > 0) {
			if (EVP_DecryptUpdate(&ctx, buf, &olen, buf,
			    bytes) == 0) {
				pjdlog_error("Unable to decrypt core.");
				goto failed;
			}
		} else {
			if (EVP_DecryptFinal_ex(&ctx, buf, &olen) == 0) {
				pjdlog_error("Unable to decrypt core.");
				goto failed;
			}
		}

		if (olen == 0)
			continue;

		if (write(ofd, buf, olen) != olen) {
			pjdlog_errno(LOG_ERR, "Unable to write data to %s",
			    output);
			goto failed;
		}
	} while (bytes > 0);

	explicit_bzero(buf, sizeof(buf));
	EVP_CIPHER_CTX_cleanup(&ctx);
	exit(0);
failed:
	explicit_bzero(key, sizeof(key));
	explicit_bzero(buf, sizeof(buf));
	RSA_free(privkey);
	EVP_CIPHER_CTX_cleanup(&ctx);
	exit(1);
}
Beispiel #7
0
int
tls_process_record_handshake(struct SSLConnection *conn, const opaque *fragment, const int len)
{
    struct Handshake *handshake;
    struct ClientHello *clienthello;
    struct ServerHello *serverhello;
    struct ClientKeyExchange *clientkeyex;
    const opaque *body;

    // Get Handshake data
    handshake = (struct Handshake *) fragment;

    if (UINT24_INT(handshake->length) > 0) {
        // Hanshake body pointer
        body = fragment + sizeof(struct Handshake);

        switch (handshake->type) {
            case hello_request:
                break;
            case client_hello:
                // Store client random
                clienthello = (struct ClientHello *) body;
                memcpy(&conn->client_random, &clienthello->random, sizeof(struct Random));

                // Check we have a TLS handshake
                if (!(clienthello->client_version.major == 0x03)) {
                    tls_connection_destroy(conn);
                    return 1;
                }

                // Only TLS 1.0, 1.1 or 1.2 connections
                if (clienthello->client_version.minor != 0x01
                        && clienthello->client_version.minor != 0x02
                        && clienthello->client_version.minor != 0x03) {
                    tls_connection_destroy(conn);
                    return 1;
                }

                // Store TLS version
                conn->version = clienthello->client_version.minor;
                break;
            case server_hello:
                // Store server random
                serverhello = (struct ServerHello *) body;
                memcpy(&conn->server_random, &serverhello->random, sizeof(struct Random));
                // Get the selected cipher
                memcpy(&conn->cipher_suite,
                       body + sizeof(struct ServerHello) + serverhello->session_id_length,
                       sizeof(uint16_t));
                // Check if we have a handled cipher
                if (tls_connection_load_cipher(conn) != 0) {
                    tls_connection_destroy(conn);
                    return 1;
                }
                break;
            case certificate:
            case certificate_request:
            case server_hello_done:
            case certificate_verify:
                break;
            case client_key_exchange:
                // Decrypt PreMasterKey
                clientkeyex = (struct ClientKeyExchange *) body;

                RSA_private_decrypt(UINT16_INT(clientkeyex->length),
                                    (const unsigned char *) &clientkeyex->exchange_keys,
                                    (unsigned char *) &conn->pre_master_secret,
                                    conn->server_private_key->pkey.rsa, RSA_PKCS1_PADDING);

                tls_debug_print_hex("client_random", &conn->client_random, 32);
                tls_debug_print_hex("server_random", &conn->server_random, 32);

                uint8_t *seed = sng_malloc(sizeof(struct Random) * 2);
                memcpy(seed, &conn->client_random, sizeof(struct Random));
                memcpy(seed + sizeof(struct Random), &conn->server_random, sizeof(struct Random));

                if (conn->version < 3) {
                    // Get MasterSecret
                    PRF((unsigned char *) &conn->master_secret, sizeof(struct MasterSecret),
                        (unsigned char *) &conn->pre_master_secret, sizeof(struct PreMasterSecret),
                        (unsigned char *) "master secret", seed, sizeof(struct Random) * 2);
                } else {
                    PRF12((unsigned char *) &conn->master_secret, sizeof(struct MasterSecret),
                          (unsigned char *) &conn->pre_master_secret, sizeof(struct PreMasterSecret),
                          (unsigned char *) "master secret", seed, sizeof(struct Random) * 2);
                }
                tls_debug_print_hex("master_secret", conn->master_secret.random, 48);

                memcpy(seed, &conn->server_random, sizeof(struct Random) * 2);
                memcpy(seed + sizeof(struct Random), &conn->client_random, sizeof(struct Random));

                // Generate MACs, Write Keys and IVs
                if (conn->version < 3) {
                    PRF((unsigned char *) &conn->key_material, sizeof(struct tls_data),
                        (unsigned char *) &conn->master_secret, sizeof(struct MasterSecret),
                        (unsigned char *) "key expansion", seed, sizeof(struct Random) * 2);
                } else {
                    PRF12((unsigned char *) &conn->key_material, sizeof(struct tls_data),
                          (unsigned char *) &conn->master_secret, sizeof(struct MasterSecret),
                          (unsigned char *) "key expansion", seed, sizeof(struct Random) * 2);
                }

                tls_debug_print_hex("client_write_MAC_key", conn->key_material.client_write_MAC_key, 20);
                tls_debug_print_hex("server_write_MAC_key", conn->key_material.server_write_MAC_key, 20);
                tls_debug_print_hex("client_write_key",     conn->key_material.client_write_key, 32);
                tls_debug_print_hex("server_write_key",     conn->key_material.server_write_key, 32);
                tls_debug_print_hex("client_write_IV",      conn->key_material.client_write_IV, 16);
                tls_debug_print_hex("server_write_IV",      conn->key_material.server_write_IV, 16);

                // Done with the seed
                sng_free(seed);

                // Create Client decoder
                EVP_CIPHER_CTX_init(&conn->client_cipher_ctx);
                EVP_CipherInit(&conn->client_cipher_ctx, conn->ciph,
                               conn->key_material.client_write_key, conn->key_material.client_write_IV,
                               0);

                EVP_CIPHER_CTX_init(&conn->server_cipher_ctx);
                EVP_CipherInit(&conn->server_cipher_ctx, conn->ciph,
                               conn->key_material.server_write_key, conn->key_material.server_write_IV,
                               0);

                break;
            case new_session_ticket:
            case finished:
                break;
            default:
                if (conn->encrypted) {
                    // Encrypted Hanshake Message
                    uint8_t *decoded = sng_malloc(len);
                    uint32_t decodedlen = len;
                    tls_process_record_data(conn, fragment, len, &decoded, &decodedlen);
                    sng_free(decoded);
                }
                break;
        }
    }

    return 0;
}
// *****************************************************************************
// *                                                                           *
// * Function: decrypt_message                                                 *
// *                                                                           *
// * Decrypt the message sent by the client                                    *
// *****************************************************************************
// *                                                                           *
// * Parameters:                                                               *
// *  <message>                 char *                    In/Out               *
// *                                                                           *
// * Returns:                                                                  *
// *                                                                           *
// *  0 if Success                                                             *
// *  SECMXO_* errors otherwise                                                *
// *                                                                           *
// *  Decrypted Message is copied back into <message>                          *
// *****************************************************************************
extern "C" int decrypt_message(char *message, char *role)
{
    short ret = 0;
    int encryption = 1;

    if (role)
       *role = 0;

    PwdKey *pwd_key = (PwdKey *) message;
    char *rolename = &pwd_key->rolename[0];
    unsigned char *pwd_key_text = (unsigned char *) &pwd_key->data;

    LoginData decrypted_data ;
    

    // check if password is a user token
    if ((message[0] == USERTOKEN_ID_1) &&
        (message[1] == USERTOKEN_ID_2))
       
       return 0;

    if (encryption)

    {
       if ( ! cipher_key )
    	    ReadPrivateKey();

       if ( ! cipher_key )
       {
          // Failure from PEM_read_PrivateKey().
          return SECMXO_PRIVKEY_FILE_ERR;
       }

       // Decrypt (session key, nonce, password).
       int key_byte_len = RSA_size(cipher_key->pkey.rsa);

       int plain_text_len = RSA_private_decrypt(key_byte_len, 
                                                pwd_key_text,
                                                (unsigned char *)&decrypted_data, 
                                                cipher_key->pkey.rsa,
                                                RSA_PKCS1_PADDING);
//     Above returns -1 if there is an error
       if (plain_text_len < 0)
       {
          return SECMXO_DECRYPTION_ERROR;
       }


       int offset = plain_text_len - SESSION_KEYLEN - NONCE_SIZE;
       decrypted_data.password[offset] = 0;            // Add two 0 as null terminator
       decrypted_data.password[++offset] = 0;

       // Build a digest and compare it with the user's.  Reject if they mismatch.
 
       if ( ! ValidateLoginDigest(&decrypted_data.session_key[0], &proc_info, pwd_key))
       {
          // Log error in EMS.
          return SECMXO_DIGEST_MISMATCH;
       }

       if (role && rolename)
       {
          while ((*rolename) != '\0')
          {
             *(role++) = toupper(*(rolename++));
          }
       }
       strcpy(message, (const char *)&decrypted_data.password);
    
    }

return 0;
}
Beispiel #9
0
int main(int argc, char *argv[]) {
  int err = 0;
  int v;
  RSA *key;
  unsigned char ptext[256];
  unsigned char ctext[256];
  static unsigned char ptext_ex[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a";
  unsigned char ctext_ex[256];
  int plen;
  int clen = 0;
  int num;
  int n;

  CRYPTO_library_init();

  plen = sizeof(ptext_ex) - 1;

  for (v = 0; v < 3; v++) {
    key = RSA_new();
    switch (v) {
      case 0:
        clen = key1(key, ctext_ex);
        break;
      case 1:
        clen = key2(key, ctext_ex);
        break;
      case 2:
        clen = key3(key, ctext_ex);
        break;
      default:
        abort();
    }

    if (!RSA_check_key(key)) {
      printf("%d: RSA_check_key failed\n", v);
      err = 1;
      goto oaep;
    }

    num = RSA_public_encrypt(plen, ptext_ex, ctext, key, RSA_PKCS1_PADDING);
    if (num != clen) {
      printf("PKCS#1 v1.5 encryption failed!\n");
      err = 1;
      goto oaep;
    }

    num = RSA_private_decrypt(num, ctext, ptext, key, RSA_PKCS1_PADDING);
    if (num != plen || memcmp(ptext, ptext_ex, num) != 0) {
      printf("PKCS#1 v1.5 decryption failed!\n");
      err = 1;
    } else {
      printf("PKCS #1 v1.5 encryption/decryption ok\n");
    }

  oaep:
    ERR_clear_error();
    num =
        RSA_public_encrypt(plen, ptext_ex, ctext, key, RSA_PKCS1_OAEP_PADDING);
    if (num == -1) {
      printf("No OAEP support\n");
      goto next;
    }
    if (num != clen) {
      printf("OAEP encryption failed!\n");
      err = 1;
      goto next;
    }

    num = RSA_private_decrypt(num, ctext, ptext, key, RSA_PKCS1_OAEP_PADDING);
    if (num != plen || memcmp(ptext, ptext_ex, num) != 0) {
      printf("OAEP decryption (encrypted data) failed!\n");
      err = 1;
    } else if (memcmp(ctext, ctext_ex, num) == 0) {
      printf("OAEP test vector %d passed!\n", v);
    }

    /* Different ciphertexts (rsa_oaep.c without -DPKCS_TESTVECT).
       Try decrypting ctext_ex */

    num =
        RSA_private_decrypt(clen, ctext_ex, ptext, key, RSA_PKCS1_OAEP_PADDING);

    if (num != plen || memcmp(ptext, ptext_ex, num) != 0) {
      printf("OAEP decryption (test vector data) failed!\n");
      err = 1;
    } else {
      printf("OAEP encryption/decryption ok\n");
    }

    /* Try decrypting corrupted ciphertexts */
    for (n = 0; n < clen; ++n) {
      int b;
      unsigned char saved = ctext[n];
      for (b = 0; b < 256; ++b) {
        if (b == saved) {
          continue;
        }
        ctext[n] = b;
        num =
            RSA_private_decrypt(num, ctext, ptext, key, RSA_PKCS1_OAEP_PADDING);
        if (num > 0) {
          printf("Corrupt data decrypted!\n");
          err = 1;
        }
      }
    }

  next:
    RSA_free(key);
  }

  if (err != 0 ||
      !test_only_d_given() ||
      !test_recover_crt_params() ||
      !test_bad_key()) {
    err = 1;
  }

  if (err == 0) {
    printf("PASS\n");
  }
  return err;
}
Beispiel #10
0
int main(int argc, char *argv[])
{
  int err=0;
  int v;
  RSA *key;
  unsigned char ptext[256];
  unsigned char ctext[256];
  static unsigned char ptext_ex[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a";
  unsigned char ctext_ex[256];
  int plen;
  int clen = 0;
  int num;
  int n;

  ENGINE *e;
  const char *engine_id = "remote";
  ENGINE_load_builtin_engines();
  e = ENGINE_by_id(engine_id);
  if(!e)
    /* the engine isn't available */
    return 1;
  if(!ENGINE_init(e)) {
    /* the engine couldn't initialise, release 'e' */
    ERR_print_errors_fp(stderr);
    ENGINE_free(e);
    return 1;
  }
  if(!ENGINE_set_default_RSA(e))
    /* This should only happen when 'e' can't initialise, but the previous
     * statement suggests it did. */
    abort();

  ENGINE_ctrl_cmd_string(e, "ADD_WORKER", "local1,127.0.0.1:1234", 0);

  CRYPTO_malloc_debug_init();
  CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
  CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

  RAND_seed(rnd_seed, sizeof rnd_seed); /* or OAEP may fail */

  plen = sizeof(ptext_ex) - 1;

  for (v = 0; v < 6; v++)
  {
    key = RSA_new();
    switch (v%3) {
      case 0:
        clen = key1(key, ctext_ex);
        break;
      case 1:
        clen = key2(key, ctext_ex);
        break;
      case 2:
        clen = key3(key, ctext_ex);
        break;
    }
    if (v/3 >= 1) key->flags |= RSA_FLAG_NO_CONSTTIME;

    num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
        RSA_PKCS1_PADDING);
    if (num != clen)
    {
      printf("PKCS#1 v1.5 encryption failed!\n");
      err=1;
      goto oaep;
    }

    num = RSA_private_decrypt(num, ctext, ptext, key,
        RSA_PKCS1_PADDING);
    if (num != plen || memcmp(ptext, ptext_ex, num) != 0)
    {
      printf("PKCS#1 v1.5 decryption failed!\n");
      err=1;
    }
    else
      printf("PKCS #1 v1.5 encryption/decryption ok\n");

oaep:
    ERR_clear_error();
    num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
        RSA_PKCS1_OAEP_PADDING);
    if (num == -1 && pad_unknown())
    {
      printf("No OAEP support\n");
      goto next;
    }
    if (num != clen)
    {
      printf("OAEP encryption failed!\n");
      err=1;
      goto next;
    }

    num = RSA_private_decrypt(num, ctext, ptext, key,
        RSA_PKCS1_OAEP_PADDING);
    if (num != plen || memcmp(ptext, ptext_ex, num) != 0)
    {
      printf("OAEP decryption (encrypted data) failed!\n");
      err=1;
    }
    else if (memcmp(ctext, ctext_ex, num) == 0)
      printf("OAEP test vector %d passed!\n", v);

    /* Different ciphertexts (rsa_oaep.c without -DPKCS_TESTVECT).
       Try decrypting ctext_ex */

    num = RSA_private_decrypt(clen, ctext_ex, ptext, key,
        RSA_PKCS1_OAEP_PADDING);

    if (num != plen || memcmp(ptext, ptext_ex, num) != 0)
    {
      printf("OAEP decryption (test vector data) failed!\n");
      err=1;
    }
    else
      printf("OAEP encryption/decryption ok\n");

    /* Try decrypting corrupted ciphertexts */
    for(n = 0 ; n < clen ; ++n)
    {
      int b;
      unsigned char saved = ctext[n];
      for(b = 0 ; b < 256 ; ++b)
      {
        if(b == saved)
          continue;
        ctext[n] = b;
        num = RSA_private_decrypt(num, ctext, ptext, key,
            RSA_PKCS1_OAEP_PADDING);
        if(num > 0)
        {
          printf("Corrupt data decrypted!\n");
          err = 1;
        }
      }
    }
next:
    RSA_free(key);
  }

  ENGINE_finish(e);
  ENGINE_free(e);

  CRYPTO_cleanup_all_ex_data();
  ERR_remove_state(0);

  CRYPTO_mem_leaks_fp(stderr);

#ifdef OPENSSL_SYS_NETWARE
  if (err) printf("ERROR: %d\n", err);
#endif
  return err;
}
Beispiel #11
0
bool metakey_h(connection_t *c) {
	char buffer[MAX_STRING_SIZE];
	int cipher, digest, maclength, compression;
	int len;

	if(sscanf(c->buffer, "%*d %d %d %d %d " MAX_STRING, &cipher, &digest, &maclength, &compression, buffer) != 5) {
		logger(LOG_ERR, "Got bad %s from %s (%s)", "METAKEY", c->name,
		       c->hostname);
		return false;
	}

	len = RSA_size(myself->connection->rsa_key);

	/* Check if the length of the meta key is all right */

	if(strlen(buffer) != (size_t)len * 2) {
		logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong keylength");
		return false;
	}

	/* Allocate buffers for the meta key */

	c->inkey = xrealloc(c->inkey, len);

	if(!c->inctx) {
		c->inctx = EVP_CIPHER_CTX_new();

		if(!c->inctx) {
			abort();
		}
	}

	/* Convert the challenge from hexadecimal back to binary */

	if(!hex2bin(buffer, buffer, len)) {
		logger(LOG_ERR, "Got bad %s from %s(%s): %s", "METAKEY", c->name, c->hostname, "invalid key");
		return false;
	}

	/* Decrypt the meta key */

	if(RSA_private_decrypt(len, (unsigned char *)buffer, (unsigned char *)c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len) {  /* See challenge() */
		logger(LOG_ERR, "Error during decryption of meta key for %s (%s): %s",
		       c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
		return false;
	}

	ifdebug(SCARY_THINGS) {
		bin2hex(c->inkey, buffer, len);
		buffer[len * 2] = '\0';
		logger(LOG_DEBUG, "Received random meta key (unencrypted): %s", buffer);
	}

	/* All incoming requests will now be encrypted. */

	/* Check and lookup cipher and digest algorithms */

	if(cipher) {
		c->incipher = EVP_get_cipherbynid(cipher);

		if(!c->incipher) {
			logger(LOG_ERR, "%s (%s) uses unknown cipher!", c->name, c->hostname);
			return false;
		}

		if(!EVP_DecryptInit(c->inctx, c->incipher,
		                    (unsigned char *)c->inkey + len - EVP_CIPHER_key_length(c->incipher),
		                    (unsigned char *)c->inkey + len - EVP_CIPHER_key_length(c->incipher) -
		                    EVP_CIPHER_iv_length(c->incipher))) {
			logger(LOG_ERR, "Error during initialisation of cipher from %s (%s): %s",
			       c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
			return false;
		}

		c->inbudget = byte_budget(c->incipher);
		c->status.decryptin = true;
	} else {
		logger(LOG_ERR, "%s (%s) uses null cipher!", c->name, c->hostname);
		return false;
	}

	c->inmaclength = maclength;

	if(digest) {
		c->indigest = EVP_get_digestbynid(digest);

		if(!c->indigest) {
			logger(LOG_ERR, "Node %s (%s) uses unknown digest!", c->name, c->hostname);
			return false;
		}

		if(c->inmaclength > EVP_MD_size(c->indigest) || c->inmaclength < 0) {
			logger(LOG_ERR, "%s (%s) uses bogus MAC length!", c->name, c->hostname);
			return false;
		}
	} else {
		logger(LOG_ERR, "%s (%s) uses null digest!", c->name, c->hostname);
		return false;
	}

	c->incompression = compression;

	c->allow_request = CHALLENGE;

	return send_challenge(c);
}
static int
xmlSecOpenSSLRsaOaepProcess(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
    xmlSecOpenSSLRsaOaepCtxPtr ctx;
    xmlSecSize paramsSize;
    xmlSecBufferPtr in, out;
    xmlSecSize inSize, outSize;
    xmlSecSize keySize;
    int ret;

    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1);
    xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1);
    xmlSecAssert2(transformCtx != NULL, -1);

    ctx = xmlSecOpenSSLRsaOaepGetCtx(transform);
    xmlSecAssert2(ctx != NULL, -1);
    xmlSecAssert2(ctx->pKey != NULL, -1);
    xmlSecAssert2(ctx->pKey->type == EVP_PKEY_RSA, -1);
    xmlSecAssert2(ctx->pKey->pkey.rsa != NULL, -1);

    keySize = RSA_size(ctx->pKey->pkey.rsa);
    xmlSecAssert2(keySize > 0, -1);

    in = &(transform->inBuf);
    out = &(transform->outBuf);

    inSize = xmlSecBufferGetSize(in);
    outSize = xmlSecBufferGetSize(out);
    xmlSecAssert2(outSize == 0, -1);

    /* the encoded size is equal to the keys size so we could not
     * process more than that */
    if((transform->operation == xmlSecTransformOperationEncrypt) && (inSize >= keySize)) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    NULL,
                    XMLSEC_ERRORS_R_INVALID_SIZE,
                    "%d when expected less than %d", inSize, keySize);
        return(-1);
    } else if((transform->operation == xmlSecTransformOperationDecrypt) && (inSize != keySize)) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    NULL,
                    XMLSEC_ERRORS_R_INVALID_SIZE,
                    "%d when expected %d", inSize, keySize);
        return(-1);
    }

    outSize = keySize;
    ret = xmlSecBufferSetMaxSize(out, outSize);
    if(ret < 0) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    "xmlSecBufferSetMaxSize",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    "size=%d", outSize);
        return(-1);
    }

    paramsSize = xmlSecBufferGetSize(&(ctx->oaepParams));
    if((transform->operation == xmlSecTransformOperationEncrypt) && (paramsSize == 0)) {
        /* encode w/o OAEPParams --> simple */
        ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in),
                                xmlSecBufferGetData(out),
                                ctx->pKey->pkey.rsa, RSA_PKCS1_OAEP_PADDING);
        if(ret <= 0) {
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                        "RSA_public_encrypt(RSA_PKCS1_OAEP_PADDING)",
                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
                        XMLSEC_ERRORS_NO_MESSAGE);
            return(-1);
        }
        outSize = ret;
    } else if((transform->operation == xmlSecTransformOperationEncrypt) && (paramsSize > 0)) {
        xmlSecAssert2(xmlSecBufferGetData(&(ctx->oaepParams)) != NULL, -1);

        /* add space for padding */
        ret = xmlSecBufferSetMaxSize(in, keySize);
        if(ret < 0) {
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                        "xmlSecBufferSetMaxSize",
                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
                        "size=%d", keySize);
            return(-1);
        }

        /* add padding */
        ret = RSA_padding_add_PKCS1_OAEP(xmlSecBufferGetData(in), keySize,
                                         xmlSecBufferGetData(in), inSize,
                                         xmlSecBufferGetData(&(ctx->oaepParams)),
                                         paramsSize);
        if(ret != 1) {
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                        "RSA_padding_add_PKCS1_OAEP",
                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
                        XMLSEC_ERRORS_NO_MESSAGE);
            return(-1);
        }
        inSize = keySize;

        /* encode with OAEPParams */
        ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in),
                                xmlSecBufferGetData(out),
                                ctx->pKey->pkey.rsa, RSA_NO_PADDING);
        if(ret <= 0) {
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                        "RSA_public_encrypt(RSA_NO_PADDING)",
                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
                        XMLSEC_ERRORS_NO_MESSAGE);
            return(-1);
        }
        outSize = ret;
    } else if((transform->operation == xmlSecTransformOperationDecrypt) && (paramsSize == 0)) {
        ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in),
                                xmlSecBufferGetData(out),
                                ctx->pKey->pkey.rsa, RSA_PKCS1_OAEP_PADDING);
        if(ret <= 0) {
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                        "RSA_private_decrypt(RSA_PKCS1_OAEP_PADDING)",
                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
                        XMLSEC_ERRORS_NO_MESSAGE);
            return(-1);
        }
        outSize = ret;
    } else if((transform->operation == xmlSecTransformOperationDecrypt) && (paramsSize != 0)) {
        BIGNUM bn;

        ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in),
                                xmlSecBufferGetData(out),
                                ctx->pKey->pkey.rsa, RSA_NO_PADDING);
        if(ret <= 0) {
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                        "RSA_private_decrypt(RSA_NO_PADDING)",
                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
                        XMLSEC_ERRORS_NO_MESSAGE);
            return(-1);
        }
        outSize = ret;

        /*
         * the private decrypt w/o padding adds '0's at the begginning.
         * it's not clear for me can I simply skip all '0's from the
         * beggining so I have to do decode it back to BIGNUM and dump
         * buffer again
         */
        BN_init(&bn);
        if(BN_bin2bn(xmlSecBufferGetData(out), outSize, &bn) == NULL) {
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                        "BN_bin2bn",
                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
                        "size=%d", outSize);
            BN_clear_free(&bn);
            return(-1);
        }

        ret = BN_bn2bin(&bn, xmlSecBufferGetData(out));
        if(ret <= 0) {
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                        "BN_bn2bin",
                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
                        XMLSEC_ERRORS_NO_MESSAGE);
            BN_clear_free(&bn);
            return(-1);
        }
        BN_clear_free(&bn);
        outSize = ret;

        ret = RSA_padding_check_PKCS1_OAEP(xmlSecBufferGetData(out), outSize,
                                           xmlSecBufferGetData(out), outSize,
                                           keySize,
                                           xmlSecBufferGetData(&(ctx->oaepParams)),
                                           paramsSize);
        if(ret < 0) {
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                        "RSA_padding_check_PKCS1_OAEP",
                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
                        XMLSEC_ERRORS_NO_MESSAGE);
            return(-1);
        }
        outSize = ret;
    } else {
        xmlSecAssert2("we could not be here" == NULL, -1);
        return(-1);
    }

    ret = xmlSecBufferSetSize(out, outSize);
    if(ret < 0) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    "xmlSecBufferSetSize",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    "size=%d", outSize);
        return(-1);
    }

    ret = xmlSecBufferRemoveHead(in, inSize);
    if(ret < 0) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    "xmlSecBufferRemoveHead",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    "size=%d", inSize);
        return(-1);
    }

    return(0);
}
static int
xmlSecOpenSSLRsaPkcs1Process(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
    xmlSecOpenSSLRsaPkcs1CtxPtr ctx;
    xmlSecBufferPtr in, out;
    xmlSecSize inSize, outSize;
    xmlSecSize keySize;
    int ret;

    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id), -1);
    xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size), -1);
    xmlSecAssert2(transformCtx != NULL, -1);

    ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform);
    xmlSecAssert2(ctx != NULL, -1);
    xmlSecAssert2(ctx->pKey != NULL, -1);
    xmlSecAssert2(ctx->pKey->type == EVP_PKEY_RSA, -1);
    xmlSecAssert2(ctx->pKey->pkey.rsa != NULL, -1);

    keySize = RSA_size(ctx->pKey->pkey.rsa);
    xmlSecAssert2(keySize > 0, -1);

    in = &(transform->inBuf);
    out = &(transform->outBuf);

    inSize = xmlSecBufferGetSize(in);
    outSize = xmlSecBufferGetSize(out);
    xmlSecAssert2(outSize == 0, -1);

    /* the encoded size is equal to the keys size so we could not
     * process more than that */
    if((transform->operation == xmlSecTransformOperationEncrypt) && (inSize >= keySize)) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    NULL,
                    XMLSEC_ERRORS_R_INVALID_SIZE,
                    "%d when expected less than %d", inSize, keySize);
        return(-1);
    } else if((transform->operation == xmlSecTransformOperationDecrypt) && (inSize != keySize)) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    NULL,
                    XMLSEC_ERRORS_R_INVALID_SIZE,
                    "%d when expected %d", inSize, keySize);
        return(-1);
    }

    outSize = keySize;
    ret = xmlSecBufferSetMaxSize(out, outSize);
    if(ret < 0) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    "xmlSecBufferSetMaxSize",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    "size=%d", outSize);
        return(-1);
    }

    if(transform->operation == xmlSecTransformOperationEncrypt) {
        ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in),
                                xmlSecBufferGetData(out),
                                ctx->pKey->pkey.rsa, RSA_PKCS1_PADDING);
        if(ret <= 0) {
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                        "RSA_public_encrypt",
                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
                        "size=%d", inSize);
            return(-1);
        }
        outSize = ret;
    } else {
        ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in),
                                xmlSecBufferGetData(out),
                                ctx->pKey->pkey.rsa, RSA_PKCS1_PADDING);
        if(ret <= 0) {
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                        "RSA_private_decrypt",
                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
                        "size=%d", inSize);
            return(-1);
        }
        outSize = ret;
    }

    ret = xmlSecBufferSetSize(out, outSize);
    if(ret < 0) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    "xmlSecBufferSetSize",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    "size=%d", outSize);
        return(-1);
    }

    ret = xmlSecBufferRemoveHead(in, inSize);
    if(ret < 0) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    "xmlSecBufferRemoveHead",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    "size=%d", inSize);
        return(-1);
    }

    return(0);
}
Beispiel #14
0
/* ========== CLIENT-MASTER-KEY ========== */
static int ssl2_decode_client_master_key(  DSSL_Session* sess, u_char* data, uint32_t len, uint32_t* processed )
{
	int rc = DSSL_RC_OK;
	uint16_t clearKeyLen = 0;
	uint16_t encKeyLen = 0;
	uint16_t keyArgLen = 0;
	u_char* pClearKey = NULL;
	u_char* pEncKey = NULL;
	u_char* pKeyArg = NULL;

	_ASSERT( processed && data && sess );
	if( len < SSL20_CLIENT_MASTER_KEY_MIN_LEN ) { return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH ); }

	/* CIPHER-KIND - convert to 2 byte DSSL_Session::cipher_suite */
	rc = DSSL_ConvertSSL2CipherSuite( data, &sess->cipher_suite );

	/* CLEAR-KEY-LENGTH, ENCRYPTED-KEY-LENGTH, KEY-ARG-LENGTH */
	if( rc == DSSL_RC_OK )
	{
		clearKeyLen = MAKE_UINT16( data[3], data[4] );
		encKeyLen = MAKE_UINT16( data[5], data[6] );
		keyArgLen = MAKE_UINT16( data[7], data[8] );

		if( len != (uint32_t)clearKeyLen + encKeyLen + keyArgLen + SSL20_CLIENT_MASTER_KEY_MIN_LEN )
		{
			rc = NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
		}

		*processed = len;

	}
	
	/* reconstitute the master secret */
	if( rc == DSSL_RC_OK )
	{
		EVP_PKEY *pk = NULL;

		pClearKey = data + SSL20_CLIENT_MASTER_KEY_MIN_LEN;
		pEncKey = pClearKey + clearKeyLen;
		pKeyArg = pEncKey + encKeyLen;

		if( clearKeyLen ) { memcpy( sess->master_secret, pClearKey, clearKeyLen ); }

		pk = ssls_get_session_private_key( sess );
		
		/* if SSL server key is not found, try to find a matching one from the key pool */
		if(pk == NULL) 
		{
			u_char buff[1024];
			_ASSERT( sess->last_packet);

			memcpy(buff, pEncKey, encKeyLen);
			pk = ssls_try_ssl_keys( sess, pEncKey, encKeyLen );

			/* if a matching key found, register it with the server IP:port */
			if(pk != NULL)
			{
				if( ssls_register_ssl_key( sess, pk ) == DSSL_RC_OK)
				{
					/* ssls_register_ssl_key clones the key, query the key back */
					//pk = ssls_get_session_private_key( sess );
				}
				else
				{
					pk = NULL;
				}
			}
		}

		if( pk )
		{
			uint32_t encLen2 = RSA_private_decrypt( encKeyLen, pEncKey, 
					sess->master_secret + clearKeyLen, pk->pkey.rsa, RSA_PKCS1_PADDING );

			if( clearKeyLen + encLen2 >= sizeof( sess->master_secret ) )
			{
				rc = NM_ERROR( DSSL_E_SSL_PROTOCOL_ERROR );
			}

			sess->master_key_len = clearKeyLen + encLen2;
		}
		else
		{
			rc = NM_ERROR( DSSL_E_SSL_SERVER_KEY_UNKNOWN );
			ssls_register_missing_key_server( sess );
		}
	}

	/* generate session keys */
	if( rc == DSSL_RC_OK )
	{
		rc = ssls2_generate_keys( sess, pKeyArg, keyArgLen );
	}

	/* turn on new ciphers */
	if( rc == DSSL_RC_OK ) 
	{
		rc = dssl_decoder_stack_flip_cipher( &sess->c_dec );
		if (rc == DSSL_RC_OK ) { rc = dssl_decoder_stack_flip_cipher( &sess->s_dec ); }
	}

	return rc;
}
Beispiel #15
0
int AuthenticateAgent(AgentConnection *conn, Attributes attr, Promise *pp)
{
    char sendbuffer[CF_EXPANDSIZE], in[CF_BUFSIZE], *out, *decrypted_cchall;
    BIGNUM *nonce_challenge, *bn = NULL;
    unsigned long err;
    unsigned char digest[EVP_MAX_MD_SIZE];
    int encrypted_len, nonce_len = 0, len, session_size;
    char dont_implicitly_trust_server, enterprise_field = 'c';
    RSA *server_pubkey = NULL;

    if (PUBKEY == NULL || PRIVKEY == NULL)
    {
        CfOut(cf_error, "", "No public/private key pair found\n");
        return false;
    }

    enterprise_field = CfEnterpriseOptions();
    session_size = CfSessionKeySize(enterprise_field);

/* Generate a random challenge to authenticate the server */

    nonce_challenge = BN_new();
    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, cf_md5);
    }

/* We assume that the server bound to the remote socket is the official one i.e. = root's */

    if ((server_pubkey = HavePublicKeyByIP(conn->username, conn->remoteip)))
    {
        dont_implicitly_trust_server = 'y';
        encrypted_len = RSA_size(server_pubkey);
    }
    else
    {
        dont_implicitly_trust_server = 'n';     /* have to trust server, since we can't verify id */
        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", dont_implicitly_trust_server, 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)
        {
            err = ERR_get_error();
            cfPS(cf_error, CF_FAIL, "", pp, attr, "Public encryption failed = %s\n", ERR_reason_error_string(err));
            free(out);
            FreeRSAKey(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->sd, sendbuffer, CF_RSA_PROTO_OFFSET + encrypted_len, CF_DONE);

    BN_free(bn);
    BN_free(nonce_challenge);
    free(out);

    if (DEBUG)
    {
        RSA_print_fp(stdout, PUBKEY, 0);
    }

/*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->sd, 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->sd, sendbuffer, len, CF_DONE);

/* check reply about public key - server can break connection here */

/* proposition S1 */
    memset(in, 0, CF_BUFSIZE);

    if (ReceiveTransaction(conn->sd, in, NULL) == -1)
    {
        cfPS(cf_error, CF_INTERPT, "recv", pp, attr, "Protocol transaction broken off (1)");
        FreeRSAKey(server_pubkey);
        return false;
    }

    if (BadProtoReply(in))
    {
        CfOut(cf_error, "", "%s", in);
        FreeRSAKey(server_pubkey);
        return false;
    }

/* Get challenge response - should be CF_DEFAULT_DIGEST of challenge */

/* proposition S2 */
    memset(in, 0, CF_BUFSIZE);

    if (ReceiveTransaction(conn->sd, in, NULL) == -1)
    {
        cfPS(cf_error, CF_INTERPT, "recv", pp, attr, "Protocol transaction broken off (2)");
        FreeRSAKey(server_pubkey);
        return false;
    }

    if (HashesMatch(digest, in, CF_DEFAULT_DIGEST) || HashesMatch(digest, in, cf_md5))  // Legacy
    {
        if (dont_implicitly_trust_server == 'y')        /* challenge reply was correct */
        {
            CfOut(cf_verbose, "", ".....................[.h.a.i.l.].................................\n");
            CfOut(cf_verbose, "", "Strong authentication of server=%s connection confirmed\n", pp->this_server);
        }
        else
        {
            if (attr.copy.trustkey)
            {
                CfOut(cf_verbose, "", " -> Trusting server identity, promise to accept key from %s=%s", pp->this_server,
                      conn->remoteip);
            }
            else
            {
                CfOut(cf_error, "", " !! Not authorized to trust the server=%s's public key (trustkey=false)\n",
                      pp->this_server);
                PromiseRef(cf_verbose, pp);
                FreeRSAKey(server_pubkey);
                return false;
            }
        }
    }
    else
    {
        cfPS(cf_error, CF_INTERPT, "", pp, attr, "Challenge response from server %s/%s was incorrect!", pp->this_server,
             conn->remoteip);
        FreeRSAKey(server_pubkey);
        return false;
    }

/* Receive counter challenge from server */

    CfDebug("Receive counter challenge from server\n");

/* proposition S3 */
    memset(in, 0, CF_BUFSIZE);
    encrypted_len = ReceiveTransaction(conn->sd, in, NULL);

    if (encrypted_len <= 0)
    {
        CfOut(cf_error, "", "Protocol transaction sent illegal cipher length");
        FreeRSAKey(server_pubkey);
        return false;
    }

    decrypted_cchall = xmalloc(encrypted_len);

    if (RSA_private_decrypt(encrypted_len, in, decrypted_cchall, PRIVKEY, RSA_PKCS1_PADDING) <= 0)
    {
        err = ERR_get_error();
        cfPS(cf_error, CF_INTERPT, "", pp, attr, "Private decrypt failed = %s, abandoning\n",
             ERR_reason_error_string(err));
        FreeRSAKey(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, cf_md5);
    }

    CfDebug("Replying to counter challenge with hash\n");

    if (FIPS_MODE)
    {
        SendTransaction(conn->sd, digest, CF_DEFAULT_DIGEST_LEN, CF_DONE);
    }
    else
    {
        SendTransaction(conn->sd, 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();

        CfOut(cf_verbose, "", " -> Collecting public key from server!\n");

        /* proposition S4 - conditional */
        if ((len = ReceiveTransaction(conn->sd, in, NULL)) <= 0)
        {
            CfOut(cf_error, "", "Protocol error in RSA authentation from IP %s\n", pp->this_server);
            return false;
        }

        if ((newkey->n = BN_mpi2bn(in, len, NULL)) == NULL)
        {
            err = ERR_get_error();
            cfPS(cf_error, CF_INTERPT, "", pp, attr, "Private key decrypt failed = %s\n", ERR_reason_error_string(err));
            FreeRSAKey(newkey);
            return false;
        }

        /* proposition S5 - conditional */

        if ((len = ReceiveTransaction(conn->sd, in, NULL)) <= 0)
        {
            cfPS(cf_inform, CF_INTERPT, "", pp, attr, "Protocol error in RSA authentation from IP %s\n",
                 pp->this_server);
            FreeRSAKey(newkey);
            return false;
        }

        if ((newkey->e = BN_mpi2bn(in, len, NULL)) == NULL)
        {
            err = ERR_get_error();
            cfPS(cf_error, CF_INTERPT, "", pp, attr, "Public key decrypt failed = %s\n", ERR_reason_error_string(err));
            FreeRSAKey(newkey);
            return false;
        }

        server_pubkey = RSAPublicKey_dup(newkey);
        FreeRSAKey(newkey);
    }

/* proposition C5 */

    SetSessionKey(conn);

    if (conn->session_key == NULL)
    {
        CfOut(cf_error, "", "A random session key could not be established");
        FreeRSAKey(server_pubkey);
        return false;
    }

    encrypted_len = RSA_size(server_pubkey);

    CfDebug("Encrypt %d bytes of session key into %d RSA bytes\n", session_size, encrypted_len);

    out = xmalloc(encrypted_len);

    if (RSA_public_encrypt(session_size, conn->session_key, out, server_pubkey, RSA_PKCS1_PADDING) <= 0)
    {
        err = ERR_get_error();
        cfPS(cf_error, CF_INTERPT, "", pp, attr, "Public encryption failed = %s\n", ERR_reason_error_string(err));
        free(out);
        FreeRSAKey(server_pubkey);
        return false;
    }

    SendTransaction(conn->sd, out, encrypted_len, CF_DONE);

    if (server_pubkey != NULL)
    {
        HashPubKey(server_pubkey, conn->digest, CF_DEFAULT_DIGEST);
        CfOut(cf_verbose, "", " -> Public key identity of host \"%s\" is \"%s\"", conn->remoteip,
              HashPrint(CF_DEFAULT_DIGEST, conn->digest));
        SavePublicKey(conn->username, conn->remoteip, HashPrint(CF_DEFAULT_DIGEST, conn->digest), server_pubkey);       // FIXME: username is local
        LastSaw(conn->remoteip, conn->digest, cf_connect);
    }

    free(out);
    FreeRSAKey(server_pubkey);
    return true;
}
Beispiel #16
0
void
ca_imsg(struct mproc *p, struct imsg *imsg)
{
	RSA			*rsa;
	const void		*from = NULL;
	unsigned char		*to = NULL;
	struct msg		 m;
	const char		*pkiname;
	size_t			 flen, tlen, padding;
	struct pki		*pki;
	int			 ret = 0;
	uint64_t		 id;
	int			 v;

	if (p->proc == PROC_PARENT) {
		switch (imsg->hdr.type) {
		case IMSG_CONF_START:
			return;
		case IMSG_CONF_END:
			ca_init();

			/* Start fulfilling requests */
			mproc_enable(p_pony);
			return;
		}
	}

	if (p->proc == PROC_CONTROL) {
		switch (imsg->hdr.type) {
		case IMSG_CTL_VERBOSE:
			m_msg(&m, imsg);
			m_get_int(&m, &v);
			m_end(&m);
			log_verbose(v);
			return;
		case IMSG_CTL_PROFILE:
			m_msg(&m, imsg);
			m_get_int(&m, &v);
			m_end(&m);
			profiling = v;
			return;
		}
	}

	if (p->proc == PROC_PONY) {
		switch (imsg->hdr.type) {
		case IMSG_CA_PRIVENC:
		case IMSG_CA_PRIVDEC:
			m_msg(&m, imsg);
			m_get_id(&m, &id);
			m_get_string(&m, &pkiname);
			m_get_data(&m, &from, &flen);
			m_get_size(&m, &tlen);
			m_get_size(&m, &padding);
			m_end(&m);

			pki = dict_get(env->sc_pki_dict, pkiname);
			if (pki == NULL || pki->pki_pkey == NULL ||
			    (rsa = EVP_PKEY_get1_RSA(pki->pki_pkey)) == NULL)
				fatalx("ca_imsg: invalid pki");

			if ((to = calloc(1, tlen)) == NULL)
				fatalx("ca_imsg: calloc");

			switch (imsg->hdr.type) {
			case IMSG_CA_PRIVENC:
				ret = RSA_private_encrypt(flen, from, to, rsa,
				    padding);
				break;
			case IMSG_CA_PRIVDEC:
				ret = RSA_private_decrypt(flen, from, to, rsa,
				    padding);
				break;
			}

			m_create(p, imsg->hdr.type, 0, 0, -1);
			m_add_id(p, id);
			m_add_int(p, ret);
			if (ret > 0)
				m_add_data(p, to, (size_t)ret);
			m_close(p);

			free(to);
			RSA_free(rsa);

			return;
		}
	}

	errx(1, "ca_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
}
Beispiel #17
0
int CRSA::RSAPrivateDecrypt( const string &strInPublicKeyN , const string &strInPublicKeyE , const string &strInPrivateKeyD ,
							const string &strInCipertext , string &strOutPlaintext , int iPadding /* = RSA_PKCS1_PADDING */ )
{	
	int iResult = 0;

	if( !strInPrivateKeyD.size() )
		return -1;
	const int ciCipertextLen = ( int )strInCipertext.size();
	if( !ciCipertextLen )
		return -1;

	RSA *pRsa = RSA_new();
	if ( !pRsa )
		return -1;

	do 
	{
		iResult = 0;

		if( !BN_hex2bn( &pRsa->n , strInPublicKeyN.c_str() ) )
		{
			iResult = -1;
			break;
		}

		if( !BN_hex2bn( &pRsa->e , strInPublicKeyE.c_str() ) )
		{
			iResult = -1;
			break;
		}

		if( !BN_hex2bn( &pRsa->d , strInPrivateKeyD.c_str() ) )
		{
			iResult = -1;
			break;
		}

		const int ciSectionFLen = RSA_size( pRsa );
		if( strInCipertext.size() % ciSectionFLen != 0 )
		{
			iResult = -1;
			break;
		}
		else
		{
			int iSignatureSize = 0;
			int iOffset = 0;
			unsigned char * pStr = ( unsigned char * )strInCipertext.c_str();
			unsigned char * pOutBuf =  new unsigned char[ciSectionFLen];
			strOutPlaintext.clear();
			while( !iResult && ( ciCipertextLen - iOffset ) )
			{
				iSignatureSize = RSA_private_decrypt( ciSectionFLen , pStr ,  pOutBuf , pRsa , iPadding );
				if ( iSignatureSize == -1 )
				{
					iResult = -1;
					strOutPlaintext.clear();			
				}			
				else strOutPlaintext.append( (char *)pOutBuf , iSignatureSize );
				iOffset += ciSectionFLen;
				pStr += ciSectionFLen;
			}
			delete [] pOutBuf;
			pOutBuf = NULL;
			pStr = NULL;
		}

	} while ( 0 );
		
	RSA_free( pRsa );
	pRsa = NULL;
	return iResult;
}
Beispiel #18
0
int KeyAuthentication(struct Image *ip)

{ char sendbuffer[CF_EXPANDSIZE],in[CF_BUFSIZE],*out,*decrypted_cchall;
 BIGNUM *nonce_challenge, *bn = NULL;
 unsigned long err;
 unsigned char digest[EVP_MAX_MD_SIZE];
 int encrypted_len,nonce_len = 0,len;
 char cant_trust_server, keyname[CF_BUFSIZE];
 RSA *server_pubkey = NULL;

if (COMPATIBILITY_MODE)
   {
   return true;
   }

if (PUBKEY == NULL || PRIVKEY == NULL) 
   {
   CfLog(cferror,"No public/private key pair found\n","");
   return false;
   }


/* Generate a random challenge to authenticate the server */
 
nonce_challenge = BN_new();
BN_rand(nonce_challenge,CF_NONCELEN,0,0);

nonce_len = BN_bn2mpi(nonce_challenge,in);
ChecksumString(in,nonce_len,digest,'m');

/* We assume that the server bound to the remote socket is the official one i.e. = root's */

if (OptionIs(CONTEXTID,"HostnameKeys",true))
   {
   snprintf(keyname,CF_BUFSIZE,"root-%s",ip->server); 
   Debug("KeyAuthentication(with hostname key %s)\n",keyname);
   }
else
   {
   snprintf(keyname,CF_BUFSIZE,"root-%s",CONN->remoteip); 
   Debug("KeyAuthentication(with IP keyname %s)\n",keyname);
   }

if (server_pubkey = HavePublicKey(keyname))
   {
   cant_trust_server = 'y';
   /* encrypted_len = BN_num_bytes(server_pubkey->n);*/   
   encrypted_len = RSA_size(server_pubkey);
   }
else 
   {
   cant_trust_server = 'n';                      /* have to trust server, since we can't verify id */
   encrypted_len = nonce_len;
   }

snprintf(sendbuffer,CF_BUFSIZE,"SAUTH %c %d %d",cant_trust_server,encrypted_len,nonce_len);
 
if ((out = malloc(encrypted_len)) == NULL)
   {
   FatalError("memory failure");
   }

if (server_pubkey != NULL)
   {
   if (RSA_public_encrypt(nonce_len,in,out,server_pubkey,RSA_PKCS1_PADDING) <= 0)
      {
      err = ERR_get_error();
      snprintf(OUTPUT,CF_BUFSIZE,"Public encryption failed = %s\n",ERR_reason_error_string(err));
      CfLog(cferror,OUTPUT,"");
      free(out);
      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->sd,sendbuffer,CF_RSA_PROTO_OFFSET+encrypted_len,CF_DONE);

BN_free(bn);
BN_free(nonce_challenge);
free(out);

if (DEBUG||D2)
   {
   RSA_print_fp(stdout,PUBKEY,0);
   }

/*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->sd,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->sd,sendbuffer,len,CF_DONE);

/* check reply about public key - server can break connection here */

/* proposition S1 */  
memset(in,0,CF_BUFSIZE);  

if (ReceiveTransaction(CONN->sd,in,NULL) == -1)
   {
   CfLog(cferror,"Protocol transaction broken off",NULL);
   return false;
   }

if (BadProtoReply(in))
   {
   CfLog(cferror,in,"");
   return false;
   }

/* Get challenge response - should be md5 of challenge */

/* proposition S2 */   
memset(in,0,CF_BUFSIZE);  

if (ReceiveTransaction(CONN->sd,in,NULL) == -1)
   {
   CfLog(cferror,"Protocol transaction broken off",NULL);
   return false;   
   }

if (!ChecksumsMatch(digest,in,'m')) 
   {
   snprintf(OUTPUT,CF_BUFSIZE,"Challenge response from server %s/%s was incorrect!",ip->server,CONN->remoteip);
   CfLog(cferror,OUTPUT,"");
   return false;
   }
else
   {
   char server[CF_EXPANDSIZE];
   ExpandVarstring(ip->server,server,NULL);
   
   if (cant_trust_server == 'y')  /* challenge reply was correct */ 
      {
      Verbose("\n...............................................................\n");
      snprintf(OUTPUT,CF_BUFSIZE,"Strong authentication of server=%s connection confirmed\n",server);
      CfLog(cfverbose,OUTPUT,"");
      }
   else
      {
      if (ip->trustkey == 'y')
         {
         snprintf(OUTPUT,CF_BUFSIZE,"Trusting server identity and willing to accept key from %s=%s",server,CONN->remoteip);
         CfLog(cferror,OUTPUT,"");
         }
      else
         {
         snprintf(OUTPUT,CF_BUFSIZE,"Not authorized to trust the server=%s's public key (trustkey=false)\n",server);
         CfLog(cferror,OUTPUT,"");
         return false;
         }
      }
   }

/* Receive counter challenge from server */ 

Debug("Receive counter challenge from server\n");  
/* proposition S3 */   
memset(in,0,CF_BUFSIZE);  
encrypted_len = ReceiveTransaction(CONN->sd,in,NULL);

if (encrypted_len < 0)
   {
   CfLog(cferror,"Protocol transaction sent illegal cipher length",NULL);
   return false;      
   }

if ((decrypted_cchall = malloc(encrypted_len)) == NULL)
   {
   FatalError("memory failure");
   }
 
if (RSA_private_decrypt(encrypted_len,in,decrypted_cchall,PRIVKEY,RSA_PKCS1_PADDING) <= 0)
   {
   err = ERR_get_error();
   snprintf(OUTPUT,CF_BUFSIZE,"Private decrypt failed = %s, abandoning\n",ERR_reason_error_string(err));
   CfLog(cferror,OUTPUT,"");
   return false;
   }

/* proposition C4 */   
ChecksumString(decrypted_cchall,nonce_len,digest,'m');
Debug("Replying to counter challenge with md5\n"); 
SendTransaction(CONN->sd,digest,16,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();

   Debug("Collecting public key from server!\n"); 

   /* proposition S4 - conditional */  
   if ((len = ReceiveTransaction(CONN->sd,in,NULL)) <= 0)
      {
      CfLog(cferror,"Protocol error in RSA authentation from IP %s\n",ip->server);
      return false;
      }
   
   if ((newkey->n = BN_mpi2bn(in,len,NULL)) == NULL)
      {
      err = ERR_get_error();
      snprintf(OUTPUT,CF_BUFSIZE,"Private decrypt failed = %s\n",ERR_reason_error_string(err));
      CfLog(cferror,OUTPUT,"");
      RSA_free(newkey);
      return false;
      }

   /* proposition S5 - conditional */  
   if ((len=ReceiveTransaction(CONN->sd,in,NULL)) == 0)
      {
      CfLog(cfinform,"Protocol error in RSA authentation from IP %s\n",ip->server);
      RSA_free(newkey);
      return false;
      }
   
   if ((newkey->e = BN_mpi2bn(in,len,NULL)) == NULL)
      {
      err = ERR_get_error();
      snprintf(OUTPUT,CF_BUFSIZE,"Private decrypt failed = %s\n",ERR_reason_error_string(err));
      CfLog(cferror,OUTPUT,"");
      RSA_free(newkey);
      return false;
      }

   SavePublicKey(keyname,newkey);
   server_pubkey = RSAPublicKey_dup(newkey);
   RSA_free(newkey);
   }
 
/* proposition C5 */

GenerateRandomSessionKey();

DebugBinOut(CONN->session_key,CF_BLOWFISHSIZE);

if (CONN->session_key == NULL)
   {
   CfLog(cferror,"A random session key could not be established","");
   return false;
   }
else
   {
   Debug("Generated session key\n");
   DebugBinOut(CONN->session_key,CF_BLOWFISHSIZE);
   }

/* blowfishmpisize = BN_bn2mpi((BIGNUM *)CONN->session_key,in); */

DebugBinOut(CONN->session_key,CF_BLOWFISHSIZE);

encrypted_len = RSA_size(server_pubkey);

Debug("Encrypt %d to %d\n",CF_BLOWFISHSIZE,encrypted_len);

if ((out = malloc(encrypted_len)) == NULL)
   {
   FatalError("memory failure");
   }

if (RSA_public_encrypt(CF_BLOWFISHSIZE,CONN->session_key,out,server_pubkey,RSA_PKCS1_PADDING) <= 0)
   {
   err = ERR_get_error();
   snprintf(OUTPUT,CF_BUFSIZE,"Public encryption failed = %s\n",ERR_reason_error_string(err));
   CfLog(cferror,OUTPUT,"");
   free(out);
   return false;
   }

Debug("Encryption succeeded\n");

SendTransaction(CONN->sd,out,encrypted_len,CF_DONE);
DebugBinOut(out,encrypted_len);

if (server_pubkey != NULL)
   {
   RSA_free(server_pubkey);
   }

free(out);
return true; 
}
Beispiel #19
0
bool ODRLLicense::extractEncryptedKey(XMLDocument* p_License, UserContext* p_Principal, OctetString* p_KeyBlob)
{
	char *encodedKey=NULL, *encodedCert=NULL;
	unsigned char *privateDecryptBuf=NULL, *kbytes=NULL;
	ByteArray *certBuf=NULL, *keyBytes=NULL;
	bool isValidKey=true;
	int val=0;
	//set the defaults for the key
	p_KeyBlob->octets = NULL;
	p_KeyBlob->len = 0;
	int kbyteLen=0;

	//now extract the key and put it into the KeyBlob
	encodedKey = p_License->getString("o-ex:agreement.o-ex:asset.ds:KeyInfo.enc:EncryptedKey.ds:KeyInfo.enc:CipherData.enc:CipherValue");

	try
	{
		if (encodedKey)
		{
			int outLen=0, saveLen=0;

			//key value found, make sure it's for this user..
			encodedCert = p_License->getString("o-ex:agreement.o-ex:asset.ds:KeyInfo.enc:EncryptedKey.ds:KeyInfo.ds:X509Data.ds:X509Certificate");
			if (!encodedCert) 
			{
				gLogger->logError("ODRLLicense::extractEncryptedKey : No matching user X509Certificate tag in License.");
				throw EXCEPTION(Exception::UNEXPECTED_CONDITION);
			}

			certBuf = RFC1521Base64::decode(encodedCert);

			if (!certBuf)
			{
				gLogger->logError("ODRLLicense::extractEncryptedKey : Error decoding User Cert B64.");
				throw EXCEPTION(Exception::UNEXPECTED_CONDITION);
			}

			//now compare the memory for the decoded cert and the current user's
			if ( (val = memcmp(p_Principal->getUserCertASN1()->octets, certBuf->data(), certBuf->length())) != 0) 
			{
				gLogger->logError("ODRLLicense::extractEncryptedKey : User Cert does not match License X509Certificate.");
				throw EXCEPTION(Exception::UNEXPECTED_CONDITION);
			}

			keyBytes = RFC1521Base64::decode(encodedKey);

			if (!keyBytes)
			{
				gLogger->logError("ODRLLicense::extractEncryptedKey : Error decoding encrypted key B64");
				throw EXCEPTION(Exception::UNEXPECTED_CONDITION);
			}

			privateDecryptBuf = new unsigned char[p_Principal->getRSAKeySize()];
			int bytesDecrypted = RSA_private_decrypt(keyBytes->length(), (unsigned char*)keyBytes->data(), privateDecryptBuf, p_Principal->getPrivateKey(), RSA_PKCS1_PADDING);
			if (bytesDecrypted != -1)
			{
				p_KeyBlob->octets = privateDecryptBuf;
				p_KeyBlob->len = bytesDecrypted;
			}
			else
			{
				gLogger->logError("ODRLLicense::extractEncryptedKey : Error decrypting License encryptedKey.");
				if (privateDecryptBuf) delete[] privateDecryptBuf;
				throw EXCEPTION(Exception::UNEXPECTED_CONDITION);
			}
		}
		//else OK?  because it's possible to require a license for unencrypted stuff.. although I don't know why in this scenario
	}
	catch (Exception&)
	{
		//TODO:  eventually will rethrow
		isValidKey = false;
	}

	if (keyBytes) delete keyBytes;
	if (encodedKey) delete[] encodedKey;
	if (encodedCert) delete encodedCert;
	if (certBuf) delete certBuf;

	return isValidKey;
}
Beispiel #20
0
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;
}
Beispiel #21
0
std::string RSAHash::RSADecrypt(const std::string &str)
{
	const char* newKey = new char[255];
	RSA_private_decrypt((int)str.length(), (const unsigned char*)str.c_str(), (unsigned char*)newKey, RSAInternal, RSA_NO_PADDING);
	return std::string(newKey);
}
Beispiel #22
0
static void
check_rsa(const unsigned char *in, size_t len, RSA *rsa, int padding)
{
    unsigned char *res, *res2;
    unsigned int len2;
    int keylen;

    res = malloc(RSA_size(rsa));
    if (res == NULL)
	errx(1, "res: ENOMEM");

    res2 = malloc(RSA_size(rsa));
    if (res2 == NULL)
	errx(1, "res2: ENOMEM");

    /* signing */

    keylen = RSA_private_encrypt(len, in, res, rsa, padding);
    if (keylen <= 0)
	errx(1, "failed to private encrypt: %d %d", (int)len, (int)keylen);

    if (keylen > RSA_size(rsa))
	errx(1, "keylen > RSA_size(rsa)");

    keylen = RSA_public_decrypt(keylen, res, res2, rsa, padding);
    if (keylen <= 0)
	errx(1, "failed to public decrypt: %d", (int)keylen);

    if (keylen != len)
	errx(1, "output buffer not same length: %d", (int)keylen);

    if (memcmp(res2, in, len) != 0)
	errx(1, "string not the same after decryption");

    /* encryption */

    keylen = RSA_public_encrypt(len, in, res, rsa, padding);
    if (keylen <= 0)
	errx(1, "failed to public encrypt: %d", (int)keylen);

    if (keylen > RSA_size(rsa))
	errx(1, "keylen > RSA_size(rsa)");

    keylen = RSA_private_decrypt(keylen, res, res2, rsa, padding);
    if (keylen <= 0)
	errx(1, "failed to private decrypt: %d", (int)keylen);

    if (keylen != len)
	errx(1, "output buffer not same length: %d", (int)keylen);

    if (memcmp(res2, in, len) != 0)
	errx(1, "string not the same after decryption");

    len2 = keylen;

    if (RSA_sign(NID_sha1, in, len, res, &len2, rsa) != 1)
	errx(1, "RSA_sign failed");

    if (RSA_verify(NID_sha1, in, len, res, len2, rsa) != 1)
	errx(1, "RSA_verify failed");

    free(res);
    free(res2);
}
Beispiel #23
0
int PacketHandler::encryption_response(User* user)
{

  if (!user->buffer.haveData(4))
  {
    return PACKET_NEED_MORE_DATA;
  }

  int16_t secretLen, verifyLen;
  std::string secret,verify;
  std::string decryptedSecret(' ', 16);

  user->buffer >> secretLen;

  if (!user->buffer.haveData(secretLen))
  {
    return PACKET_NEED_MORE_DATA;
  }

  for(int i = 0; i < secretLen; i++)
  {
    int8_t byte;
    user->buffer >> byte;
    secret.push_back(byte);
  }

  user->buffer >> verifyLen;

  if (!user->buffer.haveData(verifyLen))
  {
    return PACKET_NEED_MORE_DATA;
  }

  for(int i = 0; i < verifyLen; i++)
  {
    int8_t byte;
    user->buffer >> byte;
    verify.push_back(byte);
  }
  user->buffer.removePacket();
  
  //Those should be around 128 bytes
  if(verifyLen > 1023 || secretLen > 1023)
  {
    user->kick("Invalid verify/secret size");
    return PACKET_OK;
  }

  
  uint8_t buffer[1024];
  memset(buffer, 0, 1024);
  //Decrypt the verification bytes
  int ret = RSA_private_decrypt(verifyLen,(const uint8_t *)verify.c_str(),buffer,ServerInstance->rsa,RSA_PKCS1_PADDING);
  //Check they match with the ones sent
  if(ret != 4 || std::string((char *)buffer) != ServerInstance->encryptionBytes)
  {
    user->kick("Decryption failed");
    return PACKET_OK;
  }

  //Decrypt secret sent by the client and store
  memset(buffer, 0, 1024);
  ret = RSA_private_decrypt(secretLen,(const uint8_t *)secret.c_str(),buffer,ServerInstance->rsa,RSA_PKCS1_PADDING);
  user->secret = std::string((char *)buffer, ret);
  //We're going crypted!
  user->initCipher();
  
  
  if(!ServerInstance->config()->bData("system.user_validation"))
  {
    //Response
    user->crypted = true;
    user->buffer << (int8_t)PACKET_ENCRYPTION_RESPONSE << (int16_t)0 << (int16_t) 0;
    user->uncryptedLeft = 5; //5 first bytes are uncrypted
  }
  else
  {
    pthread_t validation_thread;
    Mineserver::userValidation* valid = new Mineserver::userValidation;
    valid->user = user;
    valid->UID = user->UID;
    pthread_create(&validation_thread,NULL,user_validation_thread,(void*)valid);
  }
  

  return PACKET_OK;
}
Beispiel #24
0
int AuthenticateAgent(AgentConnection *conn, bool trust_key)
{
    char sendbuffer[CF_EXPANDSIZE], in[CF_BUFSIZE], *out, *decrypted_cchall;
    BIGNUM *nonce_challenge, *bn = NULL;
    unsigned long err;
    unsigned char digest[EVP_MAX_MD_SIZE];
    int encrypted_len, nonce_len = 0, len, session_size;
    bool implicitly_trust_server;
    char enterprise_field = 'c';
    RSA *server_pubkey = NULL;

    if ((PUBKEY == NULL) || (PRIVKEY == NULL))
    {
        Log(LOG_LEVEL_ERR, "No public/private key pair found at %s", PublicKeyFile(GetWorkDir()));
        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 */

    if ((server_pubkey = HavePublicKeyByIP(conn->username, conn->remoteip)))
    {
        implicitly_trust_server = false;
        encrypted_len = RSA_size(server_pubkey);
    }
    else
    {
        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", 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)
        {
            err = ERR_get_error();
            Log(LOG_LEVEL_ERR, "Public encryption failed = %s", ERR_reason_error_string(err));
            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->sd, sendbuffer, CF_RSA_PROTO_OFFSET + encrypted_len, CF_DONE);

    BN_free(bn);
    BN_free(nonce_challenge);
    free(out);

    if (DEBUG)
    {
        RSA_print_fp(stdout, PUBKEY, 0);
    }

/*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->sd, 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->sd, sendbuffer, len, CF_DONE);

/* check reply about public key - server can break connection here */

/* proposition S1 */
    memset(in, 0, CF_BUFSIZE);

    if (ReceiveTransaction(conn->sd, in, NULL) == -1)
    {
        Log(LOG_LEVEL_ERR, "Protocol transaction broken off (1): %s", GetErrorStr());
        RSA_free(server_pubkey);
        return false;
    }

    if (BadProtoReply(in))
    {
        Log(LOG_LEVEL_ERR, "%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->sd, in, NULL) == -1)
    {
        Log(LOG_LEVEL_ERR, "Protocol transaction broken off (2): %s", GetErrorStr());
        RSA_free(server_pubkey);
        return false;
    }

    if ((HashesMatch(digest, in, CF_DEFAULT_DIGEST)) || (HashesMatch(digest, in, HASH_METHOD_MD5)))  // Legacy
    {
        if (implicitly_trust_server == false)        /* challenge reply was correct */
        {
            Log(LOG_LEVEL_VERBOSE, ".....................[.h.a.i.l.].................................");
            Log(LOG_LEVEL_VERBOSE, "Strong authentication of server=%s connection confirmed", conn->this_server);
        }
        else
        {
            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 the server=%s's public key (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->sd, 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)
    {
        err = ERR_get_error();
        Log(LOG_LEVEL_ERR, "Private decrypt failed = %s, abandoning",
             ERR_reason_error_string(err));
        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->sd, digest, CF_DEFAULT_DIGEST_LEN, CF_DONE);
    }
    else
    {
        SendTransaction(conn->sd, 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->sd, 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)
        {
            err = ERR_get_error();
            Log(LOG_LEVEL_ERR, "Private key decrypt failed = %s", ERR_reason_error_string(err));
            RSA_free(newkey);
            return false;
        }

        /* proposition S5 - conditional */

        if ((len = ReceiveTransaction(conn->sd, 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)
        {
            err = ERR_get_error();
            Log(LOG_LEVEL_ERR, "Public key decrypt failed = %s", ERR_reason_error_string(err));
            RSA_free(newkey);
            return false;
        }

        server_pubkey = RSAPublicKey_dup(newkey);
        RSA_free(newkey);
    }

/* 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)
    {
        err = ERR_get_error();
        Log(LOG_LEVEL_ERR, "Public encryption failed = %s", ERR_reason_error_string(err));
        free(out);
        RSA_free(server_pubkey);
        return false;
    }

    SendTransaction(conn->sd, out, encrypted_len, CF_DONE);

    if (server_pubkey != NULL)
    {
        char buffer[EVP_MAX_MD_SIZE * 4];
        HashPubKey(server_pubkey, conn->digest, CF_DEFAULT_DIGEST);
        Log(LOG_LEVEL_VERBOSE, " -> Public key identity of host \"%s\" is \"%s\"", conn->remoteip,
              HashPrintSafe(CF_DEFAULT_DIGEST, conn->digest, buffer));
        SavePublicKey(conn->username, conn->remoteip, buffer, server_pubkey);       // FIXME: username is local
        LastSaw(conn->remoteip, conn->digest, LAST_SEEN_ROLE_CONNECT);
    }

    free(out);
    RSA_free(server_pubkey);

    return true;
}
Beispiel #25
0
/* ========= ClientKeyExchange ========= */
int ssl3_decode_client_key_exchange( DSSL_Session* sess, u_char* data, uint32_t len )
{
	EVP_PKEY *pk = NULL;
	u_char* org_data = data;
	uint32_t org_len = len;
	int pms_len = 0;
	int rc = DSSL_RC_OK;

	if( sess->version < SSL3_VERSION || sess->version > TLS1_2_VERSION )
	{
		return NM_ERROR( DSSL_E_SSL_UNKNOWN_VERSION );
	}

	/* 
	TLS is different as it sends the record length, while SSL3 implementaions don't
	(due to a bug in Netscape implementation)
	*/
	if( sess->version > SSL3_VERSION )
	{
		uint16_t recLen = 0;
		if( !IS_ENOUGH_LENGTH( org_data, org_len, data, 2 ) ) 
		{
			return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
		}

		recLen = MAKE_UINT16( data[0], data[1] );
		if( len != (uint32_t)recLen + 2 )
		{
			/*TODO: set an option to tolerate this bug?*/
			return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
		}

		/* advance */
		data += len - recLen;
		len = recLen;
	}

	if( !IS_ENOUGH_LENGTH( org_data, org_len, data, SSL_MAX_MASTER_KEY_LENGTH ) )
	{
		return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
	}

	pk = ssls_get_session_private_key( sess );

	/* if SSL server key is not found, try to find a matching one from the key pool */
	if(pk == NULL) 
	{
		_ASSERT( sess->last_packet);
		pk = ssls_try_ssl_keys( sess, data, len );

		/* if a matching key found, register it with the server IP:port */
		if(pk != NULL)
		{
			if( ssls_register_ssl_key( sess, pk ) == DSSL_RC_OK)
			{
				/* ssls_register_ssl_key clones the key, query the key back */
				pk = ssls_get_session_private_key( sess );
			}
			else
			{
				pk = NULL;
			}
		}
	}

	if(!pk) 
	{
		ssls_register_missing_key_server( sess );
		return NM_ERROR( DSSL_E_SSL_SERVER_KEY_UNKNOWN );
	}

	if(pk->type != EVP_PKEY_RSA) return NM_ERROR( DSSL_E_SSL_CANNOT_DECRYPT_NON_RSA );

	pms_len = RSA_private_decrypt( len, data, sess->PMS, pk->pkey.rsa, RSA_PKCS1_PADDING );

	if( pms_len != SSL_MAX_MASTER_KEY_LENGTH )
	{
		return NM_ERROR( DSSL_E_SSL_CORRUPTED_PMS );
	}

	if( MAKE_UINT16( sess->PMS[0], sess->PMS[1] ) != sess->client_version )
	{
		return NM_ERROR( DSSL_E_SSL_PMS_VERSION_ROLLBACK );
	}

	rc = ssls_decode_master_secret( sess );
	OPENSSL_cleanse(sess->PMS, sizeof(sess->PMS) );

	if( rc != DSSL_RC_OK ) return rc;

	rc = ssls_generate_keys( sess );
	if( rc == DSSL_RC_OK )
	{
		ssls_store_session( sess );
	}
	return rc;
}
Beispiel #26
0
/*
 * js private key decrypt
*/
char * js_private_decrypt(const char *cipher_text,int length, char *private_key)
{
    RSA *rsa_privateKey = NULL;
    int rsa_private_len;
    int i;
    // private_key = rsa_key_seliaze(private_key_str);
    //BIO* p_bio = BIO_new_mem_buf(PRIVATE_KEY, -1);
    BIO* p_bio = BIO_new_mem_buf(private_key, -1);
    rsa_privateKey = PEM_read_bio_RSAPrivateKey(p_bio, NULL, 0, NULL); //
    if ( rsa_privateKey == NULL ) {
        printf("RSA is NULL\n");
        return NULL;
    }
    //printf("Cipher text: %s\n", cipher_text);
    rsa_private_len = RSA_size(rsa_privateKey);
   // printf("RSA private length: %d\n", rsa_private_len);
    size_t crypt_len = 0;
    //unsigned char *crypt = base64_decode(cipher_text, strlen(cipher_text), &crypt_len);
    char *crypt = (char *)cipher_text;
    crypt_len = length;
  //  printf("Decoded cipher: %s\nCrypt length: %ld\n", crypt, crypt_len);
    // If no static, it will cause "address of stack memory associated with local variable ...", which mean the variable will released from memory after the end of this function
    char *plain_char = malloc(crypt_len);
    memset(plain_char,0,crypt_len);
    // initialize
    strcpy(plain_char, "");
    char *err = NULL;
    for ( i = 0; i < crypt_len; i += rsa_private_len) {
        unsigned char *crypt_chunk = malloc(rsa_private_len + 1);
        memset(crypt_chunk,0,rsa_private_len + 1);
        memcpy(&crypt_chunk[0], &crypt[i], rsa_private_len);
       // printf("Crypt chunk: %s\n", crypt_chunk);
        unsigned char *result_chunk = malloc(crypt_len + 1);
        memset(result_chunk,0,crypt_len + 1);
        int result_length = RSA_private_decrypt(rsa_private_len, crypt_chunk, result_chunk, rsa_privateKey, RSA_PKCS1_PADDING);
        // chunk length should be the size of privatekey (in bytes) minus 11 (overhead during encryption)
        //  printf("Result chunk: %s\nChunk length: %d\n", result_chunk, result_length);
        free(crypt_chunk);
        // this is to omit the dummy character behind
        // i.e. Result chunk: ABC-1234567-201308101427371250-abcdefghijklmnopqrstuv\240Z
        //      Chunk length: 53
        //      New chunk: ABC-1234567-201308101427371250-abcdefghijklmnopqrstuv
        //
        // by copying the chunk to a temporary variable with an extra length (i.e. in this case is 54)
        // and then set the last character of temporary variable to NULL
        char tmp_result[result_length + 1];
        memcpy(tmp_result, result_chunk, result_length);
        tmp_result[result_length] = '\0';
       // printf("New chunk: %s\n", tmp_result);
        free(result_chunk);
        if (result_length == -1) {
            ERR_load_CRYPTO_strings();
            fprintf(stderr, "Error %s\n", ERR_error_string(ERR_get_error(), err));
            fprintf(stderr, "Error %s\n", err);
        }
        strcat(plain_char, tmp_result);
    }

    RSA_free(rsa_privateKey);
    //free(crypt);
   // printf("Final result: %s\n", plain_char);
    return plain_char;
}
Beispiel #27
0
//parseMessage(tConn->recv.data, tConn->recv.mark, &tConn->resp, ipstr, pHWADDR, tConn->keys);
static int parseMessage(struct connection *pConn, unsigned char *pIpBin, unsigned int pIpBinLen, char *pHWID)
{
  int tReturn = 0; // 0 = good, 1 = Needs More Data, -1 = close client socket.
  if(pConn->resp.data == NULL)
  {
    initBuffer(&(pConn->resp), MAX_SIZE);
  }

  char *tContent = getFromHeader(pConn->recv.data, "Content-Length", NULL);
  if(tContent != NULL)
  {
    int tContentSize = atoi(tContent);
    if(pConn->recv.marker == 0 || strlen(pConn->recv.data+pConn->recv.marker) != tContentSize)
    {
      if(isLogEnabledFor(HEADER_LOG_LEVEL))
      {
        slog(HEADER_LOG_LEVEL, "Content-Length: %s value -> %d\n", tContent, tContentSize);
        if(pConn->recv.marker != 0)
        {
          slog(HEADER_LOG_LEVEL, "ContentPtr has %d, but needs %d\n", 
                  strlen(pConn->recv.data+pConn->recv.marker), tContentSize);
        }
      }
      // check if value in tContent > 2nd read from client.
      return 1; // means more content-length needed
    }
  }
  else
  {
    slog(LOG_DEBUG_VV, "No content, header only\n");
  }

  // "Creates" a new Response Header for our response message
  addToShairBuffer(&(pConn->resp), "RTSP/1.0 200 OK\r\n");

  if(isLogEnabledFor(LOG_INFO))
  {
    int tLen = strchr(pConn->recv.data, ' ') - pConn->recv.data;
    if(tLen < 0 || tLen > 20)
    {
      tLen = 20;
    }
    slog(LOG_INFO, "********** RECV %.*s **********\n", tLen, pConn->recv.data);
  }

  if(pConn->password != NULL)
  {
    
  }

  if(buildAppleResponse(pConn, pIpBin, pIpBinLen, pHWID)) // need to free sig
  {
    slog(LOG_DEBUG_V, "Added AppleResponse to Apple-Challenge request\n");
  }

  // Find option, then based on option, do different actions.
  if(strncmp(pConn->recv.data, "OPTIONS", 7) == 0)
  {
    propogateCSeq(pConn);
    addToShairBuffer(&(pConn->resp),
      "Public: ANNOUNCE, SETUP, RECORD, PAUSE, FLUSH, TEARDOWN, OPTIONS, GET_PARAMETER, SET_PARAMETER\r\n");
  }
  else if(!strncmp(pConn->recv.data, "ANNOUNCE", 8))
  {
    char *tContent = pConn->recv.data + pConn->recv.marker;
    int tSize = 0;
    char *tHeaderVal = getFromContent(tContent, "a=aesiv", &tSize); // Not allocated memory, just pointing
    if(tSize > 0)
    {
      int tKeySize = 0;
      char tEncodedAesIV[tSize + 2];
      getTrimmed(tHeaderVal, tSize, TRUE, TRUE, tEncodedAesIV);
      slog(LOG_DEBUG_VV, "AESIV: [%.*s] Size: %d  Strlen: %d\n", tSize, tEncodedAesIV, tSize, strlen(tEncodedAesIV));
      char *tDecodedIV =  decode_base64((unsigned char*) tEncodedAesIV, tSize, &tSize);

      // grab the key, copy it out of the receive buffer
      tHeaderVal = getFromContent(tContent, "a=rsaaeskey", &tKeySize);
      char tEncodedAesKey[tKeySize + 2]; // +1 for nl, +1 for \0
      getTrimmed(tHeaderVal, tKeySize, TRUE, TRUE, tEncodedAesKey);
      slog(LOG_DEBUG_VV, "AES KEY: [%s] Size: %d  Strlen: %d\n", tEncodedAesKey, tKeySize, strlen(tEncodedAesKey));
      // remove base64 coding from key
      char *tDecodedAesKey = decode_base64((unsigned char*) tEncodedAesKey,
                              tKeySize, &tKeySize);  // Need to free DecodedAesKey

      // Grab the formats
      int tFmtpSize = 0;
      char *tFmtp = getFromContent(tContent, "a=fmtp", &tFmtpSize);  // Don't need to free
      tFmtp = getTrimmedMalloc(tFmtp, tFmtpSize, TRUE, FALSE); // will need to free
      slog(LOG_DEBUG_VV, "Format: %s\n", tFmtp);

      RSA *rsa = loadKey();
      // Decrypt the binary aes key
      char *tDecryptedKey = malloc(RSA_size(rsa) * sizeof(char)); // Need to Free Decrypted key
      //char tDecryptedKey[RSA_size(rsa)];
      if(RSA_private_decrypt(tKeySize, (unsigned char *)tDecodedAesKey, 
      (unsigned char*) tDecryptedKey, rsa, RSA_PKCS1_OAEP_PADDING) >= 0)
      {
        slog(LOG_DEBUG, "Decrypted AES key from RSA Successfully\n");
      }
      else
      {
        slog(LOG_INFO, "Error Decrypting AES key from RSA\n");
      }
      free(tDecodedAesKey);
      RSA_free(rsa);

      setKeys(pConn->keys, tDecodedIV, tDecryptedKey, tFmtp);

      propogateCSeq(pConn);
    }
  }
  else if(!strncmp(pConn->recv.data, "SETUP", 5))
  {
    // Setup pipes
    struct comms *tComms = pConn->hairtunes;
    if (! (pipe(tComms->in) == 0 && pipe(tComms->out) == 0))
    {
      slog(LOG_INFO, "Error setting up hairtunes communications...some things probably wont work very well.\n");
    }
    
    // Setup fork
    char tPort[8] = "6000";  // get this from dup()'d stdout of child pid

    int tPid = fork();
    if(tPid == 0)
    {
      int tDataport=0;
      char tCPortStr[8] = "59010";
      char tTPortStr[8] = "59012";
      int tSize = 0;

      char *tFound  =getFromSetup(pConn->recv.data, "control_port", &tSize);
      getTrimmed(tFound, tSize, 1, 0, tCPortStr);
      tFound = getFromSetup(pConn->recv.data, "timing_port", &tSize);
      getTrimmed(tFound, tSize, 1, 0, tTPortStr);

      slog(LOG_DEBUG_VV, "converting %s and %s from str->int\n", tCPortStr, tTPortStr);
      int tControlport = atoi(tCPortStr);
      int tTimingport = atoi(tTPortStr);

      slog(LOG_DEBUG_V, "Got %d for CPort and %d for TPort\n", tControlport, tTimingport);
      char *tRtp = NULL;
      char *tPipe = NULL;
      char *tAoDriver = NULL;
      char *tAoDeviceName = NULL;
      char *tAoDeviceId = NULL;

      // *************************************************
      // ** Setting up Pipes, AKA no more debug/output  **
      // *************************************************
      dup2(tComms->in[0],0);   // Input to child
      closePipe(&(tComms->in[0]));
      closePipe(&(tComms->in[1]));

      dup2(tComms->out[1], 1); // Output from child
      closePipe(&(tComms->out[1]));
      closePipe(&(tComms->out[0]));

      struct keyring *tKeys = pConn->keys;
      pConn->keys = NULL;
      pConn->hairtunes = NULL;

      // Free up any recv buffers, etc..
      if(pConn->clientSocket != -1)
      {
        close(pConn->clientSocket);
        pConn->clientSocket = -1;
      }
      cleanupBuffers(pConn);
      hairtunes_init(tKeys->aeskey, tKeys->aesiv, tKeys->fmt, tControlport, tTimingport,
                      tDataport, tRtp, tPipe, tAoDriver, tAoDeviceName, tAoDeviceId,
                      bufferStartFill);

      // Quit when finished.
      slog(LOG_DEBUG, "Returned from hairtunes init....returning -1, should close out this whole side of the fork\n");
      return -1;
    }
    else if(tPid >0)
    {
      // Ensure Connection has access to the pipe.
      closePipe(&(tComms->in[0]));
      closePipe(&(tComms->out[1]));

      char tFromHairtunes[80];
      int tRead = read(tComms->out[0], tFromHairtunes, 80);
      if(tRead <= 0)
      {
        slog(LOG_INFO, "Error reading port from hairtunes function, assuming default port: %d\n", tPort);
      }
      else
      {
        int tSize = 0;
        char *tPortStr = getFromHeader(tFromHairtunes, "port", &tSize);
        if(tPortStr != NULL)
        {
          getTrimmed(tPortStr, tSize, TRUE, FALSE, tPort);
        }
        else
        {
          slog(LOG_INFO, "Read %d bytes, Error translating %s into a port\n", tRead, tFromHairtunes);
        }
      }
      //  READ Ports from here?close(pConn->hairtunes_pipes[0]);
      propogateCSeq(pConn);
      int tSize = 0;
      char *tTransport = getFromHeader(pConn->recv.data, "Transport", &tSize);
      addToShairBuffer(&(pConn->resp), "Transport: ");
      addNToShairBuffer(&(pConn->resp), tTransport, tSize);
      // Append server port:
      addToShairBuffer(&(pConn->resp), ";server_port=");
      addToShairBuffer(&(pConn->resp), tPort);
      addToShairBuffer(&(pConn->resp), "\r\nSession: DEADBEEF\r\n");
    }
    else
    {
      slog(LOG_INFO, "Error forking process....dere' be errors round here.\n");
      return -1;
    }
  }
  else if(!strncmp(pConn->recv.data, "TEARDOWN", 8))
  {
    // Be smart?  Do more finish up stuff...
    addToShairBuffer(&(pConn->resp), "Connection: close\r\n");
    propogateCSeq(pConn);
    close(pConn->hairtunes->in[1]);
    slog(LOG_DEBUG, "Tearing down connection, closing pipes\n");
    //close(pConn->hairtunes->out[0]);
    tReturn = -1;  // Close client socket, but sends an ACK/OK packet first
  }
  else if(!strncmp(pConn->recv.data, "FLUSH", 5))
  {
    write(pConn->hairtunes->in[1], "flush\n", 6);
    propogateCSeq(pConn);
  }
  else if(!strncmp(pConn->recv.data, "SET_PARAMETER", 13))
  {
    propogateCSeq(pConn);
    int tSize = 0;
    char *tVol = getFromHeader(pConn->recv.data, "volume", &tSize);
    slog(LOG_DEBUG_VV, "About to write [vol: %.*s] data to hairtunes\n", tSize, tVol);

    write(pConn->hairtunes->in[1], "vol: ", 5);
    write(pConn->hairtunes->in[1], tVol, tSize);
    write(pConn->hairtunes->in[1], "\n", 1);
    slog(LOG_DEBUG_VV, "Finished writing data write data to hairtunes\n");
  }
  else
  {
    slog(LOG_DEBUG, "\n\nUn-Handled recv: %s\n", pConn->recv.data);
    propogateCSeq(pConn);
  }
  addToShairBuffer(&(pConn->resp), "\r\n");
  return tReturn;
}
Beispiel #28
0
//decrypts with private key
int Crypter::private_decrypt(unsigned char *enc_data, int data_len, unsigned char *decrypted){
    int result = RSA_private_decrypt(data_len, enc_data, decrypted, mPrivateRSA, padding);
    return result;
}
Beispiel #29
0
int rsautl_main(int argc, char **argv)
{
    BIO *in = NULL, *out = NULL;
    ENGINE *e = NULL;
    EVP_PKEY *pkey = NULL;
    RSA *rsa = NULL;
    X509 *x;
    char *infile = NULL, *outfile = NULL, *keyfile = NULL;
    char *passinarg = NULL, *passin = NULL, *prog;
    char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
    unsigned char *rsa_in = NULL, *rsa_out = NULL, pad = RSA_PKCS1_PADDING;
    int rsa_inlen, keyformat = FORMAT_PEM, keysize, ret = 1;
    int rsa_outlen = 0, hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0;
    OPTION_CHOICE o;

    prog = opt_init(argc, argv, rsautl_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(rsautl_options);
            ret = 0;
            goto end;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_ASN1PARSE:
            asn1parse = 1;
            break;
        case OPT_HEXDUMP:
            hexdump = 1;
            break;
        case OPT_RAW:
            pad = RSA_NO_PADDING;
            break;
        case OPT_OAEP:
            pad = RSA_PKCS1_OAEP_PADDING;
            break;
        case OPT_SSL:
            pad = RSA_SSLV23_PADDING;
            break;
        case OPT_PKCS:
            pad = RSA_PKCS1_PADDING;
            break;
        case OPT_X931:
            pad = RSA_X931_PADDING;
            break;
        case OPT_SIGN:
            rsa_mode = RSA_SIGN;
            need_priv = 1;
            break;
        case OPT_VERIFY:
            rsa_mode = RSA_VERIFY;
            break;
        case OPT_REV:
            rev = 1;
            break;
        case OPT_ENCRYPT:
            rsa_mode = RSA_ENCRYPT;
            break;
        case OPT_DECRYPT:
            rsa_mode = RSA_DECRYPT;
            need_priv = 1;
            break;
        case OPT_PUBIN:
            key_type = KEY_PUBKEY;
            break;
        case OPT_CERTIN:
            key_type = KEY_CERT;
            break;
        case OPT_INKEY:
            keyfile = opt_arg();
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        }
    }
    argc = opt_num_rest();
    if (argc != 0)
        goto opthelp;

    if (need_priv && (key_type != KEY_PRIVKEY)) {
        BIO_printf(bio_err, "A private key is needed for this operation\n");
        goto end;
    }

    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

/* FIXME: seed PRNG only if needed */
    app_RAND_load_file(NULL, 0);

    switch (key_type) {
    case KEY_PRIVKEY:
        pkey = load_key(keyfile, keyformat, 0, passin, e, "Private Key");
        break;

    case KEY_PUBKEY:
        pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "Public Key");
        break;

    case KEY_CERT:
        x = load_cert(keyfile, keyformat, "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;
    }

    in = bio_open_default(infile, 'r', FORMAT_BINARY);
    if (in == NULL)
        goto end;
    out = bio_open_default(outfile, 'w', FORMAT_BINARY);
    if (out == NULL)
        goto end;

    keysize = RSA_size(rsa);

    rsa_in = app_malloc(keysize * 2, "hold rsa key");
    rsa_out = app_malloc(keysize, "output rsa key");

    /* 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");
        goto end;
    }
    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);
    OPENSSL_free(rsa_in);
    OPENSSL_free(rsa_out);
    OPENSSL_free(passin);
    return ret;
}
int ssl_test_rsa(int argc, char *argv[])
    {
    int err=0;
    int v;
    RSA *key;
    unsigned char ptext[256];
    unsigned char ctext[256];
    static unsigned char ptext_ex[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a";
    unsigned char ctext_ex[256];
    int plen;
    int clen = 0;
    int num;
    int n;

    CRYPTO_malloc_debug_init();
    CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

    RAND_seed(rnd_seed, sizeof rnd_seed); /* or OAEP may fail */

    plen = sizeof(ptext_ex) - 1;

    for (v = 0; v < 6; v++)
	{
	key = RSA_new();
	switch (v%3) {
    case 0:
	clen = key1(key, ctext_ex);
	break;
    case 1:
	clen = key2(key, ctext_ex);
	break;
    case 2:
	clen = key3(key, ctext_ex);
	break;
	}
	if (v/3 >= 1) key->flags |= RSA_FLAG_NO_CONSTTIME;

	num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
				 RSA_PKCS1_PADDING);
	if (num != clen)
	    {
	    TINYCLR_SSL_PRINTF("PKCS#1 v1.5 encryption failed!\n");
	    err=1;
	    goto oaep;
	    }
  
	num = RSA_private_decrypt(num, ctext, ptext, key,
				  RSA_PKCS1_PADDING);
	if (num != plen || TINYCLR_SSL_MEMCMP(ptext, ptext_ex, num) != 0)
	    {
	    TINYCLR_SSL_PRINTF("PKCS#1 v1.5 decryption failed!\n");
	    err=1;
	    }
	else
	    TINYCLR_SSL_PRINTF("PKCS #1 v1.5 encryption/decryption ok\n");

    oaep:
	ERR_clear_error();
	num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
				 RSA_PKCS1_OAEP_PADDING);
	if (num == -1 && pad_unknown())
	    {
	    TINYCLR_SSL_PRINTF("No OAEP support\n");
	    goto next;
	    }
	if (num != clen)
	    {
	    TINYCLR_SSL_PRINTF("OAEP encryption failed!\n");
	    err=1;
	    goto next;
	    }

	num = RSA_private_decrypt(num, ctext, ptext, key,
				  RSA_PKCS1_OAEP_PADDING);
	if (num != plen || TINYCLR_SSL_MEMCMP(ptext, ptext_ex, num) != 0)
	    {
	    TINYCLR_SSL_PRINTF("OAEP decryption (encrypted data) failed!\n");
	    err=1;
	    }
	else if (TINYCLR_SSL_MEMCMP(ctext, ctext_ex, num) == 0)
	    TINYCLR_SSL_PRINTF("OAEP test vector %d passed!\n", v);
    
	/* Different ciphertexts (rsa_oaep.c without -DPKCS_TESTVECT).
	   Try decrypting ctext_ex */

	num = RSA_private_decrypt(clen, ctext_ex, ptext, key,
				  RSA_PKCS1_OAEP_PADDING);

	if (num != plen || TINYCLR_SSL_MEMCMP(ptext, ptext_ex, num) != 0)
	    {
	    TINYCLR_SSL_PRINTF("OAEP decryption (test vector data) failed!\n");
	    err=1;
	    }
	else
	    TINYCLR_SSL_PRINTF("OAEP encryption/decryption ok\n");

	/* Try decrypting corrupted ciphertexts */
	for(n = 0 ; n < clen ; ++n)
	    {
	    int b;
	    unsigned char saved = ctext[n];
	    for(b = 0 ; b < 256 ; ++b)
		{
		if(b == saved)
		    continue;
		ctext[n] = b;
		num = RSA_private_decrypt(num, ctext, ptext, key,
					  RSA_PKCS1_OAEP_PADDING);
		if(num > 0)
		    {
		    TINYCLR_SSL_PRINTF("Corrupt data decrypted!\n");
		    err = 1;
		    }
		}
	    }
    next:
	RSA_free(key);
	}

    CRYPTO_cleanup_all_ex_data();
    ERR_remove_thread_state(NULL);

    CRYPTO_mem_leaks_fp(OPENSSL_TYPE__FILE_STDERR);

#ifdef OPENSSL_SYS_NETWARE
    if (err) TINYCLR_SSL_PRINTF("ERROR: %d\n", err);
#endif
    return err;
    }