Exemple #1
0
/**
  Initializes user-supplied memory as TDES context for subsequent use.

  This function initializes user-supplied memory pointed by TdesContext as TDES context.
  In addition, it sets up all TDES key materials for subsequent encryption and decryption
  operations.
  There are 3 key options as follows:
  KeyLength = 64,  Keying option 1: K1 == K2 == K3 (Backward compatibility with DES)
  KeyLength = 128, Keying option 2: K1 != K2 and K3 = K1 (Less Security)
  KeyLength = 192  Keying option 3: K1 != K2 != K3 (Strongest)

  If TdesContext is NULL, then return FALSE.
  If Key is NULL, then return FALSE.
  If KeyLength is not valid, then return FALSE.

  @param[out]  TdesContext  Pointer to TDES context being initialized.
  @param[in]   Key          Pointer to the user-supplied TDES key.
  @param[in]   KeyLength    Length of TDES key in bits.

  @retval TRUE   TDES context initialization succeeded.
  @retval FALSE  TDES context initialization failed.

**/
BOOLEAN
EFIAPI
TdesInit (
  OUT  VOID         *TdesContext,
  IN   CONST UINT8  *Key,
  IN   UINTN        KeyLength
  )
{
  DES_key_schedule  *KeySchedule;

  //
  // Check input parameters.
  //
  if (TdesContext == NULL || Key == NULL || (KeyLength != 64 && KeyLength != 128 && KeyLength != 192)) {
    return FALSE;
  }

  KeySchedule = (DES_key_schedule *) TdesContext;

  //
  // If input Key is a weak key, return error.
  //
  if (DES_is_weak_key ((const_DES_cblock *) Key) == 1) {
    return FALSE;
  }

  DES_set_key_unchecked ((const_DES_cblock *) Key, KeySchedule);

  if (KeyLength == 64) {
    CopyMem (KeySchedule + 1, KeySchedule, sizeof (DES_key_schedule));
    CopyMem (KeySchedule + 2, KeySchedule, sizeof (DES_key_schedule));
    return TRUE;
  }

  if (DES_is_weak_key ((const_DES_cblock *) Key + 8) == 1) {
    return FALSE;
  }

  DES_set_key_unchecked ((const_DES_cblock *) (Key + 8), KeySchedule + 1);

  if (KeyLength == 128) {
    CopyMem (KeySchedule + 2, KeySchedule, sizeof (DES_key_schedule));
    return TRUE;
  }

  if (DES_is_weak_key ((const_DES_cblock *) Key + 16) == 1) {
    return FALSE;
  }

  DES_set_key_unchecked ((const_DES_cblock *) (Key + 16), KeySchedule + 2);

  return TRUE;
}
Exemple #2
0
static void
DES3_random_key(krb5_context context,
                krb5_keyblock *key)
{
    DES_cblock *k = key->keyvalue.data;
    do {
        krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
        DES_set_odd_parity(&k[0]);
        DES_set_odd_parity(&k[1]);
        DES_set_odd_parity(&k[2]);
    } while(DES_is_weak_key(&k[0]) ||
            DES_is_weak_key(&k[1]) ||
            DES_is_weak_key(&k[2]));
}
Exemple #3
0
void
_krb5_DES3_random_to_key(krb5_context context,
                         krb5_keyblock *key,
                         const void *data,
                         size_t size)
{
    unsigned char *x = key->keyvalue.data;
    const u_char *q = data;
    DES_cblock *k;
    int i, j;

    memset(key->keyvalue.data, 0, key->keyvalue.length);
    for (i = 0; i < 3; ++i) {
        unsigned char foo;
        for (j = 0; j < 7; ++j) {
            unsigned char b = q[7 * i + j];

            x[8 * i + j] = b;
        }
        foo = 0;
        for (j = 6; j >= 0; --j) {
            foo |= q[7 * i + j] & 1;
            foo <<= 1;
        }
        x[8 * i + 7] = foo;
    }
    k = key->keyvalue.data;
    for (i = 0; i < 3; i++) {
        DES_set_odd_parity(&k[i]);
        if(DES_is_weak_key(&k[i]))
            _krb5_xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
    }
}
Exemple #4
0
void openssl_des_crypt()
{
	int size;
	DES_cblock key;
	DES_cblock outputs;
	const_DES_cblock inputs;
	DES_key_schedule schedule;
	unsigned char tmp[16] = "des crypt";

	DES_random_key(&key);
	DES_string_to_key("beike2012", &key);
	DES_set_odd_parity(&key);
	des_check_key_parity(&key);
	DES_set_key_checked(&key, &schedule);
	DES_is_weak_key((const_DES_cblock *)tmp);
	DES_ecb_encrypt((const_DES_cblock *)tmp, &outputs, &schedule, DES_ENCRYPT);
	printf("\nDES_ecb_encrypt(%s) = ", tmp);
	for (size = 0; size < sizeof(outputs); size++)
		printf("%02x", outputs[size]);
	printf("\n");

	DES_ecb_encrypt(&outputs, &inputs, &schedule, DES_DECRYPT);
	printf("DES_ecb_decrypt(");
	for (size = 0; size < sizeof(outputs); size++)
		printf("%02x", outputs[size]);
	printf(") = %s\n", inputs);
}
Exemple #5
0
/**
 * Use NIST SP800-108 with HMAC(MD5) in counter mode as the PRF to derive a
 * des key from another type of key.
 *
 * L is 64, as we take 64 random bits and turn them into a 56-bit des key.
 * The output of hmac_md5 is 128 bits; we take the first 64 only, so n
 * properly should be 1.  However, we apply a slight variation due to the
 * possibility of producing a weak des key.  If the output key is weak, do NOT
 * simply correct it, instead, the counter is advanced and the next output
 * used.  As such, we code so as to have n be the full 255 permitted by our
 * encoding of the counter i in an 8-bit field.  L itself is encoded as a
 * 32-bit field, big-endian.  We use the constant string "rxkad" as a label
 * for this key derivation, the standard NUL byte separator, and omit a
 * key-derivation context.  The input key is unique to the krb5 service ticket,
 * which is unlikely to be used in an other location.  If it is used in such
 * a fashion, both locations will derive the same des key from the PRF, but
 * this is no different from if a krb5 des key had been used in the same way,
 * as traditional krb5 rxkad uses the ticket session key directly as the token
 * key.
 *
 * @param[in]  in      pointer to input key data
 * @param[in]  insize  length of input key data
 * @param[out] out     8-byte buffer to hold the derived key
 *
 * @return Returns 0 to indicate success, or an error code.
 *
 * @retval KRB5DES_WEAK_KEY  Successive derivation attempts with all
 * 255 possible counter values each produced weak DES keys.  This input
 * cannot be used to produce a usable key.
 */
static int
rxkad_derive_des_key(const void *in, size_t insize, char out[8])
{
    unsigned char i;
    static unsigned char label[] = "rxkad";
    /* bits of output, as 32 bit word, MSB first */
    static unsigned char Lbuf[4] = { 0, 0, 0, 64 };
    /* only needs to be 16 for md5, but lets be sure it fits */
    unsigned char tmp[64];
    unsigned int mdsize;
    DES_cblock ktmp;
    HMAC_CTX mctx;

    /* stop when 8 bit counter wraps to 0 */
    for (i = 1; i; i++) {
	HMAC_CTX_init(&mctx);
	HMAC_Init_ex(&mctx, in, insize, EVP_md5(), NULL);
	HMAC_Update(&mctx, &i, 1);
	HMAC_Update(&mctx, label, sizeof(label));   /* includes label and separator */
	HMAC_Update(&mctx, Lbuf, 4);
	mdsize = sizeof(tmp);
	HMAC_Final(&mctx, tmp, &mdsize);
	memcpy(ktmp, tmp, 8);
	DES_set_odd_parity(&ktmp);
	if (!DES_is_weak_key(&ktmp)) {
	    memcpy(out, ktmp, 8);
	    return 0;
	}
    }
    return KRB5DES_WEAK_KEY;
}
Exemple #6
0
bool
key_des_check (uint8_t *key, int key_len, int ndc)
{
  int i;
  struct buffer b;

  buf_set_read (&b, key, key_len);

  for (i = 0; i < ndc; ++i)
    {
      DES_cblock *dc = (DES_cblock*) buf_read_alloc (&b, sizeof (DES_cblock));
      if (!dc)
	{
	  msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: insufficient key material");
	  goto err;
	}
      if (DES_is_weak_key(dc))
	{
	  msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: weak key detected");
	  goto err;
	}
      if (!DES_check_key_parity (dc))
	{
	  msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: bad parity detected");
	  goto err;
	}
    }
  return true;

 err:
  ERR_clear_error ();
  return false;
}
Exemple #7
0
static void
weak_test(int is_weak, const char akey[8])
{
    DES_cblock key;
    memcpy(&key, akey, sizeof(key));
    if (DES_is_weak_key(&key) != is_weak)
	errx(1, "weakness is wrong");
}
Exemple #8
0
int DES_random_key(DES_cblock *ret)
{
    do {
        if (RAND_bytes((unsigned char *)ret, sizeof(DES_cblock)) != 1)
            return (0);
    } while (DES_is_weak_key(ret));
    DES_set_odd_parity(ret);
    return (1);
}
Exemple #9
0
int HC_DEPRECATED
DES_new_random_key(DES_cblock *key)
{
    do {
	if (RAND_bytes(key, sizeof(*key)) != 1)
	    return 1;
	DES_set_odd_parity(key);
    } while(DES_is_weak_key(key));

    return(0);
}
Exemple #10
0
/* return 0 if key parity is odd (correct),
 * return -1 if key parity error,
 * return -2 if illegal weak key.
 * return -3 if illegal parameter.
 */
int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule)
{
	if(key == NULL || schedule == NULL)
		return (-3);
	
	if (!DES_check_key_parity(key))
		return(-1);
	if (DES_is_weak_key(key))
		return(-2);
	DES_set_key_unchecked(key, schedule);
	return 0;
}
Exemple #11
0
/*
 * mit_des_is_weak_key: returns true iff key is a [semi-]weak des key.
 *
 * Requires: key has correct odd parity.
 */
int
mit_des_is_weak_key(mit_des_cblock key)
{
    unsigned int i;
    const mit_des_cblock *weak_p = weak;

    for (i = 0; i < (sizeof(weak)/sizeof(mit_des_cblock)); i++) {
        if (!memcmp(weak_p++,key,sizeof(mit_des_cblock)))
            return 1;
    }
    if ( DES_is_weak_key(key) == 1) /* Also OpenSSL's check */
        return 1;

    return 0;
}
void DES_string_to_key(const char *str, DES_cblock *key)
	{
	DES_key_schedule ks;
	int i,length;
	register unsigned char j;

	TINYCLR_SSL_MEMSET(key,0,8);
	length=TINYCLR_SSL_STRLEN(str);
#ifdef OLD_STR_TO_KEY
	for (i=0; i<length; i++)
		(*key)[i%8]^=(str[i]<<1);
#else /* MIT COMPATIBLE */
	for (i=0; i<length; i++)
		{
		j=str[i];
		if ((i%16) < 8)
			(*key)[i%8]^=(j<<1);
		else
			{
			/* Reverse the bit order 05/05/92 eay */
			j=((j<<4)&0xf0)|((j>>4)&0x0f);
			j=((j<<2)&0xcc)|((j>>2)&0x33);
			j=((j<<1)&0xaa)|((j>>1)&0x55);
			(*key)[7-(i%8)]^=j;
			}
		}
#endif
	DES_set_odd_parity(key);
#ifdef EXPERIMENTAL_STR_TO_STRONG_KEY
	if(DES_is_weak_key(key))
	    (*key)[7] ^= 0xF0;
	DES_set_key(key,&ks);
#else
	DES_set_key_unchecked(key,&ks);
#endif
	DES_cbc_cksum((const unsigned char*)str,key,length,&ks,key);
	OPENSSL_cleanse(&ks,sizeof(ks));
	DES_set_odd_parity(key);
	}
Exemple #13
0
static int fb64_start(struct fb *fbp, int dir, int server)
{
	int x;
	unsigned char *p;
	int state;

	switch (dir) {
	case DIR_DECRYPT:
		/*
		 * This is simply a request to have the other side
		 * start output (our input).  He will negotiate an
		 * IV so we need not look for it.
		 */
		state = fbp->state[dir-1];
		if (state == FAILED)
			state = IN_PROGRESS;
		break;

	case DIR_ENCRYPT:
		state = fbp->state[dir-1];
		if (state == FAILED)
			state = IN_PROGRESS;
		else if ((state & NO_SEND_IV) == 0) {
			break;
		}

		if (!VALIDKEY(fbp->krbdes_key)) {
		        fbp->need_start = 1;
			break;
		}

		state &= ~NO_SEND_IV;
		state |= NO_RECV_IV;
		if (encrypt_debug_mode)
			printf("Creating new feed\r\n");
		/*
		 * Create a random feed and send it over.
		 */
		do {
		    if (RAND_bytes(fbp->temp_feed,
				   sizeof(*fbp->temp_feed)) != 1)
			abort();
		    DES_set_odd_parity(&fbp->temp_feed);
		} while(DES_is_weak_key(&fbp->temp_feed));

		p = fbp->fb_feed + 3;
		*p++ = ENCRYPT_IS;
		p++;
		*p++ = FB64_IV;
		for (x = 0; x < sizeof(DES_cblock); ++x) {
			if ((*p++ = fbp->temp_feed[x]) == IAC)
				*p++ = IAC;
		}
		*p++ = IAC;
		*p++ = SE;
		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
		telnet_net_write(fbp->fb_feed, p - fbp->fb_feed);
		break;
	default:
		return(FAILED);
	}
	return(fbp->state[dir-1] = state);
}
Exemple #14
0
static krb5_error_code
DES3_string_to_key(krb5_context context,
		   krb5_enctype enctype,
		   krb5_data password,
		   krb5_salt salt,
		   krb5_data opaque,
		   krb5_keyblock *key)
{
    char *str;
    size_t len;
    unsigned char tmp[24];
    DES_cblock keys[3];
    krb5_error_code ret;

    len = password.length + salt.saltvalue.length;
    str = malloc(len);
    if(len != 0 && str == NULL) {
	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
	return ENOMEM;
    }
    memcpy(str, password.data, password.length);
    memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
    {
	DES_cblock ivec;
	DES_key_schedule s[3];
	int i;

	ret = _krb5_n_fold(str, len, tmp, 24);
	if (ret) {
	    memset(str, 0, len);
	    free(str);
	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	    return ret;
	}

	for(i = 0; i < 3; i++){
	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
	    DES_set_odd_parity(keys + i);
	    if(DES_is_weak_key(keys + i))
		_krb5_xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
	    DES_set_key_unchecked(keys + i, &s[i]);
	}
	memset(&ivec, 0, sizeof(ivec));
	DES_ede3_cbc_encrypt(tmp,
			     tmp, sizeof(tmp),
			     &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
	memset(s, 0, sizeof(s));
	memset(&ivec, 0, sizeof(ivec));
	for(i = 0; i < 3; i++){
	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
	    DES_set_odd_parity(keys + i);
	    if(DES_is_weak_key(keys + i))
		_krb5_xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
	}
	memset(tmp, 0, sizeof(tmp));
    }
    key->keytype = enctype;
    krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
    memset(keys, 0, sizeof(keys));
    memset(str, 0, len);
    free(str);
    return 0;
}
Exemple #15
0
static int
WorkerBee(struct cmd_syndesc *as, void *arock)
{
    afs_int32 code;
    char *dbFile;
    char *outFile;
    afs_int32 index;
    struct stat info;
    struct kaheader header;
    int nentries, i, j, count;
    int *entrys;
    struct kaentry entry;

    dbFile = as->parms[0].items->data;	/* -database */
    listuheader = (as->parms[1].items ? 1 : 0);	/* -uheader  */
    listkheader = (as->parms[2].items ? 1 : 0);	/* -kheader  */
    listentries = (as->parms[3].items ? 1 : 0);	/* -entries  */
    verbose = (as->parms[4].items ? 1 : 0);	/* -verbose  */
    outFile = (as->parms[5].items ? as->parms[5].items->data : NULL);	/* -rebuild  */

    if (outFile) {
	out = fopen(outFile, "w");
	if (!out) {
	    afs_com_err(whoami, errno, "opening output file %s", outFile);
	    exit(7);
	}
    } else
	out = 0;

    fd = open(dbFile, O_RDONLY, 0);
    if (fd < 0) {
	afs_com_err(whoami, errno, "opening database file %s", dbFile);
	exit(6);
    }
    code = fstat(fd, &info);
    if (code) {
	afs_com_err(whoami, errno, "stat'ing file %s", dbFile);
	exit(6);
    }
    if ((info.st_size - UBIK_HEADERSIZE) % UBIK_BUFFERSIZE)
	fprintf(stderr,
		"DATABASE SIZE INCONSISTENT: was %d, should be (n*%d + %d), for integral n\n",
		(int) info.st_size, UBIK_BUFFERSIZE, UBIK_HEADERSIZE);

    readUbikHeader();

    readDB(0, &header, sizeof(header));
    code = CheckHeader(&header);
    if (listkheader)
	PrintHeader(&header);

    nentries =
	(info.st_size -
	 (UBIK_HEADERSIZE + header.headerSize)) / sizeof(struct kaentry);
    entrys = calloc(nentries, sizeof(int));

    for (i = 0, index = sizeof(header); i < nentries;
	 i++, index += sizeof(struct kaentry)) {
	readDB(index, &entry, sizeof(entry));

	if (index >= header.eofPtr) {
	    entrys[i] |= 0x8;
	} else if (listentries) {
	    PrintEntry(index, &entry);
	}

	if (entry.flags & KAFNORMAL) {
	    entrys[i] |= 0x1;	/* user entry */

	    if (strlen(entry.userID.name) == 0) {
		if (verbose)
		    printf("Entry %d has zero length name\n", i);
		continue;
	    }
	    if (!DES_check_key_parity(ktc_to_cblock(&entry.key))
		|| DES_is_weak_key(ktc_to_cblock(&entry.key))) {
		fprintf(stderr, "Entry %d, %s, has bad key\n", i,
			EntryName(&entry));
		continue;
	    }

	    if (out) {
		RebuildEntry(&entry);
	    }

	} else if (entry.flags & KAFFREE) {
	    entrys[i] |= 0x2;	/* free entry */

	} else if (entry.flags & KAFOLDKEYS) {
	    entrys[i] |= 0x4;	/* old keys block */
	    /* Should check the structure of the oldkeys block? */

	} else {
	    if (index < header.eofPtr) {
		fprintf(stderr, "Entry %d is unrecognizable\n", i);
	    }
	}
    }

    /* Follow the hash chains */
    for (j = 0; j < HASHSIZE; j++) {
	for (index = header.nameHash[j]; index; index = entry.next) {
	    readDB(index, &entry, sizeof(entry));

	    /* check to see if the name is hashed correctly */
	    i = NameHash(&entry);
	    if (i != j) {
		fprintf(stderr,
			"Entry %" AFS_SIZET_FMT ", %s, found in hash chain %d (should be %d)\n",
			((index -
			  sizeof(struct kaheader)) / sizeof(struct kaentry)),
			EntryName(&entry), j, i);
	    }

	    /* Is it on another hash chain or circular hash chain */
	    i = (index - header.headerSize) / sizeof(entry);
	    if (entrys[i] & 0x10) {
		fprintf(stderr,
			"Entry %d, %s, hash index %d, was found on another hash chain\n",
			i, EntryName(&entry), j);
		if (entry.next)
		    fprintf(stderr, "Skipping rest of hash chain %d\n", j);
		else
		    fprintf(stderr, "No next entry in hash chain %d\n", j);
		code++;
		break;
	    }
	    entrys[i] |= 0x10;	/* On hash chain */
	}
    }

    /* Follow the free pointers */
    count = 0;
    for (index = header.freePtr; index; index = entry.next) {
	readDB(index, &entry, sizeof(entry));

	/* Is it on another chain or circular free chain */
	i = (index - header.headerSize) / sizeof(entry);
	if (entrys[i] & 0x20) {
	    fprintf(stderr, "Entry %d, %s, already found on free chain\n", i,
		    EntryName(&entry));
	    fprintf(stderr, "Skipping rest of free chain\n");
	    code++;
	    break;
	}
	entrys[i] |= 0x20;	/* On free chain */

	count++;
    }
    if (verbose)
	printf("Found %d free entries\n", count);

    /* Follow the oldkey blocks */
    count = 0;
    for (index = header.kvnoPtr; index; index = entry.next) {
	readDB(index, &entry, sizeof(entry));

	/* Is it on another chain or circular free chain */
	i = (index - header.headerSize) / sizeof(entry);
	if (entrys[i] & 0x40) {
	    fprintf(stderr, "Entry %d, %s, already found on olkeys chain\n",
		    i, EntryName(&entry));
	    fprintf(stderr, "Skipping rest of oldkeys chain\n");
	    code++;
	    break;
	}
	entrys[i] |= 0x40;	/* On free chain */

	count++;
    }
    if (verbose)
	printf("Found %d oldkey blocks\n", count);

    /* Now recheck all the blocks and see if they are allocated correctly
     * 0x1 --> User Entry           0x10 --> On hash chain
     * 0x2 --> Free Entry           0x20 --> On Free chain
     * 0x4 --> OldKeys Entry        0x40 --> On Oldkeys chain
     * 0x8 --> Past EOF
     */
    for (i = 0; i < nentries; i++) {
	j = entrys[i];
	if (j & 0x1) {		/* user entry */
	    if (!(j & 0x10))
		badEntry(j, i);	/* on hash chain? */
	    else if (j & 0xee)
		badEntry(j, i);	/* anything else? */
	} else if (j & 0x2) {	/* free entry */
	    if (!(j & 0x20))
		badEntry(j, i);	/* on free chain? */
	    else if (j & 0xdd)
		badEntry(j, i);	/* anything else? */
	} else if (j & 0x4) {	/* oldkeys entry */
	    if (!(j & 0x40))
		badEntry(j, i);	/* on oldkeys chain? */
	    else if (j & 0xbb)
		badEntry(j, i);	/* anything else? */
	} else if (j & 0x8) {	/* past eof */
	    if (j & 0xf7)
		badEntry(j, i);	/* anything else? */
	} else
	    badEntry(j, i);	/* anything else? */
    }

    exit(code != 0);
}
Exemple #16
0
int _ossl_old_des_is_weak_key(_ossl_old_des_cblock *key)
  {
  return DES_is_weak_key(key);
  }
void DES_string_to_2keys(const char *str, DES_cblock *key1, DES_cblock *key2)
	{
	DES_key_schedule ks;
	int i,length;
	register unsigned char j;

	TINYCLR_SSL_MEMSET(key1,0,8);
	TINYCLR_SSL_MEMSET(key2,0,8);
	length=TINYCLR_SSL_STRLEN(str);
#ifdef OLD_STR_TO_KEY
	if (length <= 8)
		{
		for (i=0; i<length; i++)
			{
			(*key2)[i]=(*key1)[i]=(str[i]<<1);
			}
		}
	else
		{
		for (i=0; i<length; i++)
			{
			if ((i/8)&1)
				(*key2)[i%8]^=(str[i]<<1);
			else
				(*key1)[i%8]^=(str[i]<<1);
			}
		}
#else /* MIT COMPATIBLE */
	for (i=0; i<length; i++)
		{
		j=str[i];
		if ((i%32) < 16)
			{
			if ((i%16) < 8)
				(*key1)[i%8]^=(j<<1);
			else
				(*key2)[i%8]^=(j<<1);
			}
		else
			{
			j=((j<<4)&0xf0)|((j>>4)&0x0f);
			j=((j<<2)&0xcc)|((j>>2)&0x33);
			j=((j<<1)&0xaa)|((j>>1)&0x55);
			if ((i%16) < 8)
				(*key1)[7-(i%8)]^=j;
			else
				(*key2)[7-(i%8)]^=j;
			}
		}
	if (length <= 8) TINYCLR_SSL_MEMCPY(key2,key1,8);
#endif
	DES_set_odd_parity(key1);
	DES_set_odd_parity(key2);
#ifdef EXPERIMENTAL_STR_TO_STRONG_KEY
	if(DES_is_weak_key(key1))
	    (*key1)[7] ^= 0xF0;
	DES_set_key(key1,&ks);
#else
	DES_set_key_unchecked(key1,&ks);
#endif
	DES_cbc_cksum((const unsigned char*)str,key1,length,&ks,key1);
#ifdef EXPERIMENTAL_STR_TO_STRONG_KEY
	if(DES_is_weak_key(key2))
	    (*key2)[7] ^= 0xF0;
	DES_set_key(key2,&ks);
#else
	DES_set_key_unchecked(key2,&ks);
#endif
	DES_cbc_cksum((const unsigned char*)str,key2,length,&ks,key2);
	OPENSSL_cleanse(&ks,sizeof(ks));
	DES_set_odd_parity(key1);
	DES_set_odd_parity(key2);
	}