Esempio n. 1
0
afs_int32
rxkad_EncryptPacket(const struct rx_connection * conn,
		    const fc_KeySchedule * schedule,
		    const fc_InitializationVector * ivec, const int inlen,
		    struct rx_packet * packet)
{
    afs_uint32 xor[2];
    struct rx_securityClass *obj;
    struct rxkad_cprivate *tp;	/* s & c have type at same offset */
    char *data;
    int i, tlen, len;

    len = inlen;

    obj = rx_SecurityObjectOf(conn);
    tp = (struct rxkad_cprivate *)obj->privateData;
    ADD_RXKAD_STATS(bytesEncrypted[rxkad_TypeIndex(tp->type)],len);
    /*
     * afs_int32 cksum;
     * cksum = htonl(0);
     * * Future option to add cksum here, but for now we just put 0
     */
    rx_PutInt32(packet, 1 * sizeof(afs_int32), 0);

    memcpy((void *)xor, (void *)ivec, sizeof(xor));
    for (i = 0; len; i++) {
	data = rx_data(packet, i, tlen);
	if (!data || !tlen)
	    break;
	tlen = MIN(len, tlen);
	fc_cbc_encrypt(data, data, tlen, *schedule, xor, ENCRYPT);
	len -= tlen;
    }
    return 0;
}
Esempio n. 2
0
afs_int32
rxkad_DecryptPacket(const struct rx_connection *conn,
		    const fc_KeySchedule * schedule,
		    const fc_InitializationVector * ivec, const int inlen,
		    struct rx_packet *packet)
{
    afs_uint32 xor[2];
    struct rx_securityClass *obj;
    struct rxkad_cprivate *tp;	/* s & c have type at same offset */
    char *data;
    int i, tlen, len;

    len = inlen;

    obj = rx_SecurityObjectOf(conn);
    tp = (struct rxkad_cprivate *)obj->privateData;
    ADD_RXKAD_STATS(bytesDecrypted[rxkad_TypeIndex(tp->type)],len);
    memcpy((void *)xor, (void *)ivec, sizeof(xor));
    for (i = 0; len; i++) {
	data = rx_data(packet, i, tlen);
	if (!data || !tlen)
	    break;
	tlen = MIN(len, tlen);
	fc_cbc_encrypt(data, data, tlen, *schedule, xor, DECRYPT);
	len -= tlen;
    }
    /* Do this if packet checksums are ever enabled (below), but
     * current version just passes zero
     afs_int32 cksum;
     cksum = ntohl(rx_GetInt32(packet, 1));
     */
    return 0;
}
Esempio n. 3
0
/* allocate a new connetion ID in place */
int
rxkad_AllocCID(struct rx_securityClass *aobj, struct rx_connection *aconn)
{
    struct rxkad_cprivate *tcp;
    struct rxkad_cidgen tgen;
    static afs_int32 counter = 0;	/* not used anymore */

    LOCK_CUID;
    if (Cuid[0] == 0) {
	afs_uint32 xor[2];
	tgen.ipAddr = rxi_getaddr();	/* comes back in net order */
	clock_GetTime(&tgen.time);	/* changes time1 and time2 */
	tgen.time.sec = htonl(tgen.time.sec);
	tgen.time.usec = htonl(tgen.time.usec);
	tgen.counter = htonl(counter);
	counter++;
#ifdef KERNEL
	tgen.random1 = afs_random() & 0x7fffffff;	/* was "80000" */
	tgen.random2 = afs_random() & 0x7fffffff;	/* was "htonl(100)" */
#else
	tgen.random1 = htonl(getpid());
	tgen.random2 = htonl(100);
#endif
	if (aobj) {
	    /* block is ready for encryption with session key, let's go for it. */
	    tcp = (struct rxkad_cprivate *)aobj->privateData;
	    memcpy((void *)xor, (void *)tcp->ivec, 2 * sizeof(afs_int32));
	    fc_cbc_encrypt((char *)&tgen, (char *)&tgen, sizeof(tgen),
			   tcp->keysched, xor, ENCRYPT);
	} else {
	    /* Create a session key so that we can encrypt it */

	}
	memcpy((void *)Cuid,
	       ((char *)&tgen) + sizeof(tgen) - ENCRYPTIONBLOCKSIZE,
	       ENCRYPTIONBLOCKSIZE);
	Cuid[0] = (Cuid[0] & ~0x40000000) | 0x80000000;
	Cuid[1] &= RX_CIDMASK;
	rx_SetEpoch(Cuid[0]);	/* for future rxnull connections */
	rxkad_EpochWasSet++;
    }

    if (!aconn) {
	UNLOCK_CUID;
	return 0;
    }
    aconn->epoch = Cuid[0];
    aconn->cid = Cuid[1];
    Cuid[1] += 1 << RX_CIDSHIFT;
    UNLOCK_CUID;
    return 0;
}
Esempio n. 4
0
/* XXX this does some copying of data in and out of the packet, but I'll bet it
 * could just do it in place, especially if I used rx_Pullup...
 */
int
rxkad_CheckResponse(struct rx_securityClass *aobj,
		    struct rx_connection *aconn, struct rx_packet *apacket)
{
    struct rxkad_sconn *sconn;
    struct rxkad_sprivate *tsp;
    struct ktc_encryptionKey serverKey;
    struct rxkad_oldChallengeResponse oldr;	/* response format */
    struct rxkad_v2ChallengeResponse v2r;
    afs_int32 tlen;		/* ticket len */
    afs_int32 kvno;		/* key version of ticket */
    char tix[MAXKTCTICKETLEN];
    afs_int32 incChallengeID;
    rxkad_level level;
    int code;
    /* ticket contents */
    struct ktc_principal client;
    struct ktc_encryptionKey sessionkey;
    afs_int32 host;
    afs_uint32 start;
    afs_uint32 end;
    unsigned int pos;
    struct rxkad_serverinfo *rock;

    sconn = (struct rxkad_sconn *)aconn->securityData;
    tsp = (struct rxkad_sprivate *)aobj->privateData;

    if (sconn->cksumSeen) {
	/* expect v2 response, leave fields in v2r in network order for cksum
	 * computation which follows decryption. */
	if (rx_GetDataSize(apacket) < sizeof(v2r))
	    return RXKADPACKETSHORT;
	rx_packetread(apacket, 0, sizeof(v2r), &v2r);
	pos = sizeof(v2r);
	/* version == 2 */
	/* ignore spare */
	kvno = ntohl(v2r.kvno);
	tlen = ntohl(v2r.ticketLen);
	if (rx_GetDataSize(apacket) < sizeof(v2r) + tlen)
	    return RXKADPACKETSHORT;
    } else {
	/* expect old format response */
	if (rx_GetDataSize(apacket) < sizeof(oldr))
	    return RXKADPACKETSHORT;
	rx_packetread(apacket, 0, sizeof(oldr), &oldr);
	pos = sizeof(oldr);

	kvno = ntohl(oldr.kvno);
	tlen = ntohl(oldr.ticketLen);
	if (rx_GetDataSize(apacket) != sizeof(oldr) + tlen)
	    return RXKADPACKETSHORT;
    }
    if ((tlen < MINKTCTICKETLEN) || (tlen > MAXKTCTICKETLEN))
	return RXKADTICKETLEN;

    rx_packetread(apacket, pos, tlen, tix);	/* get ticket */

    /*
     * We allow the ticket to be optionally decoded by an alternate
     * ticket decoder, if the function variable
     * rxkad_AlternateTicketDecoder is set. That function should
     * return a code of -1 if it wants the ticket to be decoded by
     * the standard decoder.
     */
    if (rxkad_AlternateTicketDecoder) {
	code =
	    rxkad_AlternateTicketDecoder(kvno, tix, tlen, client.name,
					 client.instance, client.cell,
					 &sessionkey, &host, &start, &end);
	if (code && code != -1) {
	    return code;
	}
    } else {
	code = -1;		/* No alternate ticket decoder present */
    }

    /*
     * If the alternate decoder is not present, or returns -1, then
     * assume the ticket is of the default style.
     */
    if (code == -1 && ((kvno == RXKAD_TKT_TYPE_KERBEROS_V5)
	|| (kvno == RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY))) {
	code =
	    tkt_DecodeTicket5(tix, tlen, tsp->get_key, tsp->get_key_rock,
			      kvno, client.name, client.instance, client.cell,
			      &sessionkey, &host, &start, &end, 
			      tsp->flags & RXS_CONFIG_FLAGS_DISABLE_DOTCHECK);
	if (code)
	    return code;
    }

    /*
     * If the alternate decoder/kerberos 5 decoder is not present, or
     * returns -1, then assume the ticket is of the default style.
     */
    if (code == -1) {
	/* get ticket's key */
	code = (*tsp->get_key) (tsp->get_key_rock, kvno, &serverKey);
	if (code)
	    return RXKADUNKNOWNKEY;	/* invalid kvno */
	code =
	    tkt_DecodeTicket(tix, tlen, &serverKey, client.name,
			     client.instance, client.cell, &sessionkey, &host,
			     &start, &end);
	if (code)
	    return code;
    }
    code = tkt_CheckTimes(start, end, time(0));
    if (code == 0) 
	return RXKADNOAUTH;
    else if (code == -1)
	return RXKADEXPIRED;
    else if (code < -1)
	return RXKADBADTICKET;

    code = fc_keysched(&sessionkey, sconn->keysched);
    if (code)
	return RXKADBADKEY;
    memcpy(sconn->ivec, &sessionkey, sizeof(sconn->ivec));

    if (sconn->cksumSeen) {
	/* using v2 response */
	afs_uint32 cksum;	/* observed cksum */
	struct rxkad_endpoint endpoint;	/* connections endpoint */
	int i;
	afs_uint32 xor[2];

	memcpy(xor, sconn->ivec, 2 * sizeof(afs_int32));
	fc_cbc_encrypt(&v2r.encrypted, &v2r.encrypted, sizeof(v2r.encrypted),
		       sconn->keysched, xor, DECRYPT);
	cksum = rxkad_CksumChallengeResponse(&v2r);
	if (cksum != v2r.encrypted.endpoint.cksum)
	    return RXKADSEALEDINCON;
	(void)rxkad_SetupEndpoint(aconn, &endpoint);
	v2r.encrypted.endpoint.cksum = 0;
	if (memcmp(&endpoint, &v2r.encrypted.endpoint, sizeof(endpoint)) != 0)
	    return RXKADSEALEDINCON;
	for (i = 0; i < RX_MAXCALLS; i++) {
	    v2r.encrypted.callNumbers[i] =
		ntohl(v2r.encrypted.callNumbers[i]);
	    if (v2r.encrypted.callNumbers[i] < 0)
		return RXKADSEALEDINCON;
	}

	(void)rxi_SetCallNumberVector(aconn, v2r.encrypted.callNumbers);
	incChallengeID = ntohl(v2r.encrypted.incChallengeID);
	level = ntohl(v2r.encrypted.level);
    } else {
	/* expect old format response */
	fc_ecb_encrypt(&oldr.encrypted, &oldr.encrypted, sconn->keysched,
		       DECRYPT);
	incChallengeID = ntohl(oldr.encrypted.incChallengeID);
	level = ntohl(oldr.encrypted.level);
    }
    if (incChallengeID != sconn->challengeID + 1)
	return RXKADOUTOFSEQUENCE;	/* replay attempt */
    if ((level < sconn->level) || (level > rxkad_crypt))
	return RXKADLEVELFAIL;
    sconn->level = level;
    rxkad_SetLevel(aconn, sconn->level);
    INC_RXKAD_STATS(responses[rxkad_LevelIndex(sconn->level)]);
    /* now compute endpoint-specific info used for computing 16 bit checksum */
    rxkad_DeriveXORInfo(aconn, sconn->keysched, sconn->ivec, sconn->preSeq);

    /* otherwise things are ok */
    sconn->expirationTime = end;
    sconn->authenticated = 1;

    if (tsp->user_ok) {
	code = tsp->user_ok(client.name, client.instance, client.cell, kvno);
	if (code)
	    return RXKADNOAUTH;
    } else {			/* save the info for later retreival */
	int size = sizeof(struct rxkad_serverinfo);
	rock = (struct rxkad_serverinfo *)osi_Alloc(size);
	memset(rock, 0, size);
	rock->kvno = kvno;
	memcpy(&rock->client, &client, sizeof(rock->client));
	sconn->rock = rock;
    }
    return 0;
}
Esempio n. 5
0
int
main(void)
{
    int32 sched[ROUNDS];
    char ciph[100], clear[100];
    u_int32 data[2];
    u_int32 iv[2];
    struct rx_connection conn;
    struct rx_securityClass obj;
    struct rxkad_cprivate cpriv;
    struct rx_packet packet;
    int fail = 0;

    conn.securityObject = &obj;
    obj.privateData = (void *)&cpriv;
    cpriv.type = 0;

    if (sizeof(int32) != 4) {
	fprintf(stderr, "error: sizeof(int32) != 4\n");
	fail++;
    }
    if (sizeof(u_int32) != 4) {
	fprintf(stderr, "error: sizeof(u_int32) != 4\n");
	fail++;
    }

    /*
     * Use key1 and key2 as iv */
    fc_keysched((struct ktc_encryptionKey *)key1, sched);
    memcpy(iv, key2, sizeof(iv));
    fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT);
    if (memcmp(ciph1, ciph, sizeof(ciph1)) != 0) {
	fprintf(stderr, "encrypt FAILED\n");
	fail++;
    }
    memcpy(iv, key2, sizeof(iv));
    fc_cbc_encrypt(ciph, clear, sizeof(the_quick), sched, iv, DECRYPT);
    if (strcmp(the_quick, clear) != 0) {
	fprintf(stderr, "crypt decrypt FAILED\n");
	fail++;
    }

    /*
     * Use key2 and key1 as iv
     */
    fc_keysched((struct ktc_encryptionKey *)key2, sched);
    memcpy(iv, key1, sizeof(iv));
    fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT);
    if (memcmp(ciph2, ciph, sizeof(ciph2)) != 0) {
	fprintf(stderr, "encrypt FAILED\n");
	fail++;
    }
    memcpy(iv, key1, sizeof(iv));
    fc_cbc_encrypt(ciph, clear, sizeof(the_quick), sched, iv, DECRYPT);
    if (strcmp(the_quick, clear) != 0) {
	fprintf(stderr, "crypt decrypt FAILED\n");
	fail++;
    }

    /*
     * Test Encrypt- and Decrypt-Packet, use key1 and key2 as iv
     */
    fc_keysched((struct ktc_encryptionKey *)key1, sched);
    memcpy(iv, key2, sizeof(iv));
    strcpy(clear, the_quick);
    packet.wirevec[1].iov_base = clear;
    packet.wirevec[1].iov_len = sizeof(the_quick);
    packet.wirevec[2].iov_len = 0;

    /* For unknown reasons bytes 4-7 are zeroed in rxkad_EncryptPacket */
    rxkad_EncryptPacket(&conn, sched, iv, sizeof(the_quick), &packet);
    rxkad_DecryptPacket(&conn, sched, iv, sizeof(the_quick), &packet);
    clear[4] ^= 'q';
    clear[5] ^= 'u';
    clear[6] ^= 'i';
    clear[7] ^= 'c';
    if (strcmp(the_quick, clear) != 0)
	fprintf(stderr, "rxkad_EncryptPacket/rxkad_DecryptPacket FAILED\n");

    {
	struct timeval start, stop;
	int i;

	fc_keysched((struct ktc_encryptionKey *)key1, sched);
	gettimeofday(&start, NULL);
	for (i = 0; i < 1000000; i++)
	    fc_keysched((struct ktc_encryptionKey *)key1, sched);
	gettimeofday(&stop, NULL);
	printf("fc_keysched    = %2.2f us\n",
	       (stop.tv_sec - start.tv_sec +
		(stop.tv_usec - start.tv_usec) / 1e6) * 1);

	fc_ecb_encrypt(data, data, sched, ENCRYPT);
	gettimeofday(&start, NULL);
	for (i = 0; i < 1000000; i++)
	    fc_ecb_encrypt(data, data, sched, ENCRYPT);
	gettimeofday(&stop, NULL);
	printf("fc_ecb_encrypt = %2.2f us\n",
	       (stop.tv_sec - start.tv_sec +
		(stop.tv_usec - start.tv_usec) / 1e6) * 1);

	fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv,
		       ENCRYPT);
	gettimeofday(&start, NULL);
	for (i = 0; i < 100000; i++)
	    fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv,
			   ENCRYPT);
	gettimeofday(&stop, NULL);
	printf("fc_cbc_encrypt = %2.2f us\n",
	       (stop.tv_sec - start.tv_sec +
		(stop.tv_usec - start.tv_usec) / 1e6) * 10);

    }

    exit(fail);
}
Esempio n. 6
0
int
rxkad_GetResponse(struct rx_securityClass *aobj, struct rx_connection *aconn,
		  struct rx_packet *apacket)
{
    struct rxkad_cprivate *tcp;
    char *tp;
    int v2;			/* whether server is old style or v2 */
    afs_int32 challengeID;
    rxkad_level level;
    char *response;
    int responseSize, missing;
    struct rxkad_v2ChallengeResponse r_v2;
    struct rxkad_oldChallengeResponse r_old;

    tcp = (struct rxkad_cprivate *)aobj->privateData;

    if (!(tcp->type & rxkad_client))
	return RXKADINCONSISTENCY;

    v2 = (rx_Contiguous(apacket) > sizeof(struct rxkad_oldChallenge));
    tp = rx_DataOf(apacket);

    if (v2) {			/* v2 challenge */
	struct rxkad_v2Challenge *c_v2;
	if (rx_GetDataSize(apacket) < sizeof(struct rxkad_v2Challenge))
	    return RXKADPACKETSHORT;
	c_v2 = (struct rxkad_v2Challenge *)tp;
	challengeID = ntohl(c_v2->challengeID);
	level = ntohl(c_v2->level);
    } else {			/* old format challenge */
	struct rxkad_oldChallenge *c_old;
	if (rx_GetDataSize(apacket) < sizeof(struct rxkad_oldChallenge))
	    return RXKADPACKETSHORT;
	c_old = (struct rxkad_oldChallenge *)tp;
	challengeID = ntohl(c_old->challengeID);
	level = ntohl(c_old->level);
    }

    if (level > tcp->level)
	return RXKADLEVELFAIL;
    INC_RXKAD_STATS(challenges[rxkad_LevelIndex(tcp->level)]);
    if (v2) {
	int i;
	afs_uint32 xor[2];
	memset((void *)&r_v2, 0, sizeof(r_v2));
	r_v2.version = htonl(RXKAD_CHALLENGE_PROTOCOL_VERSION);
	r_v2.spare = 0;
	(void)rxkad_SetupEndpoint(aconn, &r_v2.encrypted.endpoint);
	(void)rxi_GetCallNumberVector(aconn, r_v2.encrypted.callNumbers);
	for (i = 0; i < RX_MAXCALLS; i++) {
	    if (r_v2.encrypted.callNumbers[i] < 0)
		return RXKADINCONSISTENCY;
	    r_v2.encrypted.callNumbers[i] =
		htonl(r_v2.encrypted.callNumbers[i]);
	}
	r_v2.encrypted.incChallengeID = htonl(challengeID + 1);
	r_v2.encrypted.level = htonl((afs_int32) tcp->level);
	r_v2.kvno = htonl(tcp->kvno);
	r_v2.ticketLen = htonl(tcp->ticketLen);
	r_v2.encrypted.endpoint.cksum = rxkad_CksumChallengeResponse(&r_v2);
	memcpy((void *)xor, (void *)tcp->ivec, 2 * sizeof(afs_int32));
	fc_cbc_encrypt(&r_v2.encrypted, &r_v2.encrypted,
		       sizeof(r_v2.encrypted), tcp->keysched, xor, ENCRYPT);
	response = (char *)&r_v2;
	responseSize = sizeof(r_v2);
    } else {
	memset((void *)&r_old, 0, sizeof(r_old));
	r_old.encrypted.incChallengeID = htonl(challengeID + 1);
	r_old.encrypted.level = htonl((afs_int32) tcp->level);
	r_old.kvno = htonl(tcp->kvno);
	r_old.ticketLen = htonl(tcp->ticketLen);
	fc_ecb_encrypt(&r_old.encrypted, &r_old.encrypted, tcp->keysched,
		       ENCRYPT);
	response = (char *)&r_old;
	responseSize = sizeof(r_old);
    }

    if (RX_MAX_PACKET_DATA_SIZE < responseSize + tcp->ticketLen)
	return RXKADPACKETSHORT;	/* not enough space */

    rx_computelen(apacket, missing);
    missing = responseSize + tcp->ticketLen - missing;
    if (missing > 0)
	if (rxi_AllocDataBuf(apacket, missing, RX_PACKET_CLASS_SEND) > 0)
	    return RXKADPACKETSHORT;	/* not enough space */

    /* copy response and ticket into packet */
    rx_packetwrite(apacket, 0, responseSize, response);
    rx_packetwrite(apacket, responseSize, tcp->ticketLen, tcp->ticket);

    rx_SetDataSize(apacket, responseSize + tcp->ticketLen);
    return 0;
}