static void test_wrapping(krb5_context context, size_t min_size, size_t max_size, size_t step, krb5_enctype etype) { krb5_error_code ret; krb5_keyblock key; krb5_crypto crypto; krb5_data data; char *etype_name; void *buf; size_t size; ret = krb5_generate_random_keyblock(context, etype, &key); if (ret) krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); ret = krb5_enctype_to_string(context, etype, &etype_name); if (ret) krb5_err(context, 1, ret, "krb5_enctype_to_string"); buf = malloc(max_size); if (buf == NULL) krb5_errx(context, 1, "out of memory"); memset(buf, 0, max_size); ret = krb5_crypto_init(context, &key, 0, &crypto); if (ret) krb5_err(context, 1, ret, "krb5_crypto_init"); for (size = min_size; size < max_size; size += step) { size_t wrapped_size; ret = krb5_encrypt(context, crypto, 0, buf, size, &data); if (ret) krb5_err(context, 1, ret, "encrypt size %lu using %s", (unsigned long)size, etype_name); wrapped_size = krb5_get_wrapped_length(context, crypto, size); if (wrapped_size != data.length) krb5_errx(context, 1, "calculated wrapped length %lu != " "real wrapped length %lu for data length %lu using " "enctype %s", (unsigned long)wrapped_size, (unsigned long)data.length, (unsigned long)size, etype_name); krb5_data_free(&data); } free(etype_name); free(buf); krb5_crypto_destroy(context, crypto); krb5_free_keyblock_contents(context, &key); }
static void time_encryption(krb5_context context, size_t size, krb5_enctype etype, int iterations) { struct timeval tv1, tv2; krb5_error_code ret; krb5_keyblock key; krb5_crypto crypto; krb5_data data; char *etype_name; void *buf; int i; ret = krb5_generate_random_keyblock(context, etype, &key); if (ret) krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); ret = krb5_enctype_to_string(context, etype, &etype_name); if (ret) krb5_err(context, 1, ret, "krb5_enctype_to_string"); buf = malloc(size); if (buf == NULL) krb5_errx(context, 1, "out of memory"); memset(buf, 0, size); ret = krb5_crypto_init(context, &key, 0, &crypto); if (ret) krb5_err(context, 1, ret, "krb5_crypto_init"); gettimeofday(&tv1, NULL); for (i = 0; i < iterations; i++) { ret = krb5_encrypt(context, crypto, 0, buf, size, &data); if (ret) krb5_err(context, 1, ret, "encrypt: %d", i); krb5_data_free(&data); } gettimeofday(&tv2, NULL); timevalsub(&tv2, &tv1); printf("%s size: %7lu iterations: %d time: %3ld.%06ld\n", etype_name, (unsigned long)size, iterations, (long)tv2.tv_sec, (long)tv2.tv_usec); free(buf); free(etype_name); krb5_crypto_destroy(context, crypto); krb5_free_keyblock_contents(context, &key); }
u32 gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text, struct xdr_netobj *token) { struct krb5_ctx *ctx = gss_ctx->internal_ctx_id; char cksumdata[16]; struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; unsigned char *ptr, *krb5_hdr, *msg_start; s32 now; u32 seq_send; dprintk("RPC: gss_krb5_seal\n"); BUG_ON(ctx == NULL); now = get_seconds(); token->len = g_token_size(&ctx->mech_used, 22); ptr = token->data; g_make_token_header(&ctx->mech_used, 22, &ptr); *ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff); *ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff); /* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */ krb5_hdr = ptr - 2; msg_start = krb5_hdr + 24; *(__be16 *)(krb5_hdr + 2) = htons(SGN_ALG_DES_MAC_MD5); memset(krb5_hdr + 4, 0xff, 4); if (make_checksum("md5", krb5_hdr, 8, text, 0, &md5cksum)) return GSS_S_FAILURE; if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, md5cksum.len)) return GSS_S_FAILURE; memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH, KRB5_CKSUM_LENGTH); spin_lock(&krb5_seq_lock); seq_send = ctx->seq_send++; spin_unlock(&krb5_seq_lock); if (krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff, ctx->seq_send, krb5_hdr + 16, krb5_hdr + 8)) return GSS_S_FAILURE; return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; }
static krb5_error_code storage_to_etext(krb5_context context, krb5_storage *sp, const krb5_keyblock *key, krb5_data *enc_data) { krb5_error_code ret; krb5_crypto crypto; krb5_ssize_t size; krb5_data data; /* multiple of eight bytes */ size = krb5_storage_seek(sp, 0, SEEK_END); if (size < 0) return EINVAL; size = 8 - (size & 7); ret = krb5_storage_write(sp, eightzeros, size); if (ret != size) return EINVAL; ret = krb5_storage_to_data(sp, &data); if (ret) return ret; ret = krb5_crypto_init(context, key, ETYPE_DES_PCBC_NONE, &crypto); if (ret) { krb5_data_free(&data); return ret; } ret = krb5_encrypt(context, crypto, 0, data.data, data.length, enc_data); krb5_data_free(&data); krb5_crypto_destroy(context, crypto); return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_mk_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf) { krb5_error_code ret; AP_REP ap; EncAPRepPart body; u_char *buf = NULL; size_t buf_size; size_t len = 0; krb5_crypto crypto; ap.pvno = 5; ap.msg_type = krb_ap_rep; memset (&body, 0, sizeof(body)); body.ctime = auth_context->authenticator->ctime; body.cusec = auth_context->authenticator->cusec; if (auth_context->flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) { if (auth_context->local_subkey == NULL) { ret = krb5_auth_con_generatelocalsubkey(context, auth_context, auth_context->keyblock); if(ret) { free_EncAPRepPart(&body); return ret; } } ret = krb5_copy_keyblock(context, auth_context->local_subkey, &body.subkey); if (ret) { free_EncAPRepPart(&body); return krb5_enomem(context); } } else body.subkey = NULL; if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { if(auth_context->local_seqnumber == 0) krb5_generate_seq_number (context, auth_context->keyblock, &auth_context->local_seqnumber); ALLOC(body.seq_number, 1); if (body.seq_number == NULL) { free_EncAPRepPart(&body); return krb5_enomem(context); } *(body.seq_number) = auth_context->local_seqnumber; } else body.seq_number = NULL; ap.enc_part.etype = auth_context->keyblock->keytype; ap.enc_part.kvno = NULL; ASN1_MALLOC_ENCODE(EncAPRepPart, buf, buf_size, &body, &len, ret); free_EncAPRepPart (&body); if(ret) return ret; if (buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); ret = krb5_crypto_init(context, auth_context->keyblock, 0 /* ap.enc_part.etype */, &crypto); if (ret) { free (buf); return ret; } ret = krb5_encrypt (context, crypto, KRB5_KU_AP_REQ_ENC_PART, buf + buf_size - len, len, &ap.enc_part.cipher); krb5_crypto_destroy(context, crypto); free(buf); if (ret) return ret; ASN1_MALLOC_ENCODE(AP_REP, outbuf->data, outbuf->length, &ap, &len, ret); if (ret == 0 && outbuf->length != len) krb5_abortx(context, "internal error in ASN.1 encoder"); free_AP_REP (&ap); return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_build_authenticator (krb5_context context, krb5_auth_context auth_context, krb5_enctype enctype, krb5_creds *cred, Checksum *cksum, krb5_data *result, krb5_key_usage usage) { Authenticator auth; u_char *buf = NULL; size_t buf_size; size_t len = 0; krb5_error_code ret; krb5_crypto crypto; memset(&auth, 0, sizeof(auth)); auth.authenticator_vno = 5; copy_Realm(&cred->client->realm, &auth.crealm); copy_PrincipalName(&cred->client->name, &auth.cname); krb5_us_timeofday (context, &auth.ctime, &auth.cusec); ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth.subkey); if(ret) goto fail; if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { if(auth_context->local_seqnumber == 0) krb5_generate_seq_number (context, &cred->session, &auth_context->local_seqnumber); ALLOC(auth.seq_number, 1); if(auth.seq_number == NULL) { ret = ENOMEM; goto fail; } *auth.seq_number = auth_context->local_seqnumber; } else auth.seq_number = NULL; auth.authorization_data = NULL; if (cksum) { ALLOC(auth.cksum, 1); if (auth.cksum == NULL) { ret = ENOMEM; goto fail; } ret = copy_Checksum(cksum, auth.cksum); if (ret) goto fail; if (auth.cksum->cksumtype == CKSUMTYPE_GSSAPI) { /* * This is not GSS-API specific, we only enable it for * GSS for now */ ret = make_etypelist(context, &auth.authorization_data); if (ret) goto fail; } } /* XXX - Copy more to auth_context? */ auth_context->authenticator->ctime = auth.ctime; auth_context->authenticator->cusec = auth.cusec; ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, &auth, &len, ret); if (ret) goto fail; if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); ret = krb5_crypto_init(context, &cred->session, enctype, &crypto); if (ret) goto fail; ret = krb5_encrypt (context, crypto, usage /* KRB5_KU_AP_REQ_AUTH */, buf, len, result); krb5_crypto_destroy(context, crypto); if (ret) goto fail; fail: free_Authenticator (&auth); free (buf); return ret; }
krb5_error_code kcm_store_io(krb5_context context, krb5_uuid uuid, void *ptr, size_t length, krb5_data *data, bool encrypt) { xtsEncrypt_InStruct_t xtsEncrypt_InStruct; size_t inseed_size = 64; io_connect_t conn; kern_return_t kr; uint8_t *inseed; krb5_crypto crypto = NULL; krb5_error_code ret; krb5_data_zero(data); inseed = malloc(inseed_size); if (inseed == NULL) err(1, "malloc"); memset(inseed, 0, inseed_size); conn = openiodev(); if (conn == IO_OBJECT_NULL) { free(inseed); return EINVAL; } uuid_copy(xtsEncrypt_InStruct.key_uuid, uuid); xtsEncrypt_InStruct.bufferAddress = (uint64_t) (intptr_t) inseed; xtsEncrypt_InStruct.bufferLength = (uint64_t) inseed_size; memset(xtsEncrypt_InStruct.tweak, 0, XTS_TWEAK_BYTES); kr = IOConnectCallMethod(conn, kAppleFDEKeyStore_xtsEncrypt, NULL, 0, & xtsEncrypt_InStruct, sizeof(xtsEncrypt_InStruct), NULL, 0, NULL, 0); closeiodev(conn); if (kr != KERN_SUCCESS) { free(inseed); return EINVAL; } CC_SHA256(inseed, (CC_LONG)inseed_size, inseed); krb5_keyblock keyblock; keyblock.keytype = ETYPE_AES128_CTS_HMAC_SHA1_96; keyblock.keyvalue.data = inseed; keyblock.keyvalue.length = 16; ret = krb5_crypto_init(context, &keyblock, 0, &crypto); free(inseed); if (ret) return ret; if (encrypt) ret = krb5_encrypt(context, crypto, 1, ptr, length, data); else ret = krb5_decrypt(context, crypto, 1, ptr, length, data); krb5_crypto_destroy(context, crypto); return ret; }
u32 krb5_make_token(struct krb5_ctx *ctx, int qop_req, struct xdr_netobj * text, struct xdr_netobj * token, int toktype) { s32 checksum_type; struct xdr_netobj md5cksum = {.len = 0, .data = NULL}; int blocksize = 0, tmsglen; unsigned char *ptr, *krb5_hdr, *msg_start; s32 now; dprintk("RPC: gss_krb5_seal"); now = jiffies; if (qop_req != 0) goto out_err; switch (ctx->signalg) { case SGN_ALG_DES_MAC_MD5: checksum_type = CKSUMTYPE_RSA_MD5; break; default: dprintk("RPC: gss_krb5_seal: ctx->signalg %d not" " supported\n", ctx->signalg); goto out_err; } if (ctx->sealalg != SEAL_ALG_NONE && ctx->sealalg != SEAL_ALG_DES) { dprintk("RPC: gss_krb5_seal: ctx->sealalg %d not supported\n", ctx->sealalg); goto out_err; } if (toktype == KG_TOK_WRAP_MSG) { blocksize = crypto_tfm_alg_blocksize(ctx->enc); tmsglen = blocksize + text->len + gss_krb5_padding(blocksize, blocksize + text->len); } else { tmsglen = 0; } token->len = g_token_size(&ctx->mech_used, 22 + tmsglen); if ((token->data = kmalloc(token->len, GFP_KERNEL)) == NULL) goto out_err; ptr = token->data; g_make_token_header(&ctx->mech_used, 22 + tmsglen, &ptr, toktype); /* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */ krb5_hdr = ptr - 2; msg_start = krb5_hdr + 24; *(u16 *)(krb5_hdr + 2) = htons(ctx->signalg); memset(krb5_hdr + 4, 0xff, 4); if (toktype == KG_TOK_WRAP_MSG) *(u16 *)(krb5_hdr + 4) = htons(ctx->sealalg); if (toktype == KG_TOK_WRAP_MSG) { unsigned char pad = gss_krb5_padding(blocksize, text->len); get_random_bytes(msg_start, blocksize); /* "confounder" */ memcpy(msg_start + blocksize, text->data, text->len); memset(msg_start + blocksize + text->len, pad, pad); if (compute_checksum(checksum_type, krb5_hdr, msg_start, tmsglen, &md5cksum)) goto out_err; if (krb5_encrypt(ctx->enc, NULL, msg_start, msg_start, tmsglen)) goto out_err; } else { /* Sign only. */ if (compute_checksum(checksum_type, krb5_hdr, text->data, text->len, &md5cksum)) goto out_err; } switch (ctx->signalg) { case SGN_ALG_DES_MAC_MD5: if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, md5cksum.len)) goto out_err; memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - CKSUM_SIZE, CKSUM_SIZE); dprintk("make_seal_token: cksum data: \n"); print_hexl((u32 *) (krb5_hdr + 16), CKSUM_SIZE, 0); break; default: BUG(); } kfree(md5cksum.data); if ((krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff, ctx->seq_send, krb5_hdr + 16, krb5_hdr + 8))) goto out_err; ctx->seq_send++; return ((ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE); out_err: if (md5cksum.data) kfree(md5cksum.data); if (token->data) kfree(token->data); token->data = 0; token->len = 0; return GSS_S_FAILURE; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_mk_priv(krb5_context context, krb5_auth_context auth_context, const krb5_data *userdata, krb5_data *outbuf, krb5_replay_data *outdata) { krb5_error_code ret; KRB_PRIV s; EncKrbPrivPart part; u_char *buf = NULL; size_t buf_size; size_t len = 0; krb5_crypto crypto; krb5_keyblock *key; krb5_replay_data rdata; if ((auth_context->flags & (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && outdata == NULL) return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ if (auth_context->local_subkey) key = auth_context->local_subkey; else if (auth_context->remote_subkey) key = auth_context->remote_subkey; else key = auth_context->keyblock; memset(&rdata, 0, sizeof(rdata)); part.user_data = *userdata; krb5_us_timeofday (context, &rdata.timestamp, &rdata.usec); if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { part.timestamp = &rdata.timestamp; part.usec = &rdata.usec; } else { part.timestamp = NULL; part.usec = NULL; } if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_TIME) { outdata->timestamp = rdata.timestamp; outdata->usec = rdata.usec; } if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { rdata.seq = auth_context->local_seqnumber; part.seq_number = &rdata.seq; } else part.seq_number = NULL; if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) outdata->seq = auth_context->local_seqnumber; part.s_address = auth_context->local_address; part.r_address = auth_context->remote_address; krb5_data_zero (&s.enc_part.cipher); ASN1_MALLOC_ENCODE(EncKrbPrivPart, buf, buf_size, &part, &len, ret); if (ret) goto fail; if (buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); s.pvno = 5; s.msg_type = krb_priv; s.enc_part.etype = key->keytype; s.enc_part.kvno = NULL; ret = krb5_crypto_init(context, key, 0, &crypto); if (ret) { free (buf); return ret; } ret = krb5_encrypt (context, crypto, KRB5_KU_KRB_PRIV, buf + buf_size - len, len, &s.enc_part.cipher); krb5_crypto_destroy(context, crypto); if (ret) { free(buf); return ret; } free(buf); ASN1_MALLOC_ENCODE(KRB_PRIV, buf, buf_size, &s, &len, ret); if (ret) goto fail; if (buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); krb5_data_free (&s.enc_part.cipher); ret = krb5_data_copy(outbuf, buf + buf_size - len, len); if (ret) { free(buf); return krb5_enomem(context); } free (buf); if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) auth_context->local_seqnumber = (auth_context->local_seqnumber + 1) & 0xFFFFFFFF; return 0; fail: free (buf); krb5_data_free (&s.enc_part.cipher); return ret; }
u32 krb5_read_token(struct krb5_ctx *ctx, struct xdr_netobj *read_token, struct xdr_netobj *message_buffer, int *qop_state, int toktype) { s32 code; int tmsglen = 0; int conflen = 0; int signalg; int sealalg; struct xdr_netobj token = {.len = 0, .data = NULL}; s32 checksum_type; struct xdr_netobj cksum; struct xdr_netobj md5cksum = {.len = 0, .data = NULL}; struct xdr_netobj plaind; char *data_ptr; s32 now; unsigned char *plain = NULL; int cksum_len = 0; int plainlen = 0; int direction; s32 seqnum; unsigned char *ptr = (unsigned char *)read_token->data; int bodysize; u32 ret = GSS_S_DEFECTIVE_TOKEN; dprintk("RPC: krb5_read_token\n"); if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used, &bodysize, &ptr, toktype, read_token->len)) goto out; if (toktype == KG_TOK_WRAP_MSG) { message_buffer->len = 0; message_buffer->data = NULL; } /* get the sign and seal algorithms */ signalg = ptr[0] + (ptr[1] << 8); sealalg = ptr[2] + (ptr[3] << 8); /* Sanity checks */ if ((ptr[4] != 0xff) || (ptr[5] != 0xff)) goto out; if (((toktype != KG_TOK_WRAP_MSG) && (sealalg != 0xffff)) || ((toktype == KG_TOK_WRAP_MSG) && (sealalg == 0xffff))) goto out; /* in the current spec, there is only one valid seal algorithm per key type, so a simple comparison is ok */ if ((toktype == KG_TOK_WRAP_MSG) && !(sealalg == ctx->sealalg)) goto out; /* there are several mappings of seal algorithms to sign algorithms, but few enough that we can try them all. */ if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) || (ctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) || (ctx->sealalg == SEAL_ALG_DES3KD && signalg != SGN_ALG_HMAC_SHA1_DES3_KD)) goto out; /* starting with a single alg */ switch (signalg) { case SGN_ALG_DES_MAC_MD5: cksum_len = 8; break; default: goto out; } if (toktype == KG_TOK_WRAP_MSG) tmsglen = bodysize - (14 + cksum_len); /* get the token parameters */ /* decode the message, if WRAP */ if (toktype == KG_TOK_WRAP_MSG) { dprintk("RPC: krb5_read_token KG_TOK_WRAP_MSG\n"); plain = kmalloc(tmsglen, GFP_KERNEL); ret = GSS_S_FAILURE; if (plain == NULL) goto out; code = krb5_decrypt(ctx->enc, NULL, ptr + 14 + cksum_len, plain, tmsglen); if (code) goto out; plainlen = tmsglen; conflen = crypto_tfm_alg_blocksize(ctx->enc); token.len = tmsglen - conflen - plain[tmsglen - 1]; if (token.len) { token.data = kmalloc(token.len, GFP_KERNEL); if (token.data == NULL) goto out; memcpy(token.data, plain + conflen, token.len); } } else if (toktype == KG_TOK_MIC_MSG) { dprintk("RPC: krb5_read_token KG_TOK_MIC_MSG\n"); token = *message_buffer; plain = token.data; plainlen = token.len; } else { token.len = 0; token.data = NULL; plain = token.data; plainlen = token.len; } dprintk("RPC krb5_read_token: token.len %d plainlen %d\n", token.len, plainlen); /* compute the checksum of the message */ /* initialize the the cksum */ switch (signalg) { case SGN_ALG_DES_MAC_MD5: checksum_type = CKSUMTYPE_RSA_MD5; break; default: ret = GSS_S_DEFECTIVE_TOKEN; goto out; } switch (signalg) { case SGN_ALG_DES_MAC_MD5: dprintk("RPC krb5_read_token SGN_ALG_DES_MAC_MD5\n"); /* compute the checksum of the message. * 8 = bytes of token body to be checksummed according to spec */ data_ptr = kmalloc(8 + plainlen, GFP_KERNEL); ret = GSS_S_FAILURE; if (!data_ptr) goto out; memcpy(data_ptr, ptr - 2, 8); memcpy(data_ptr + 8, plain, plainlen); plaind.len = 8 + plainlen; plaind.data = data_ptr; code = krb5_make_checksum(checksum_type, &plaind, &md5cksum); kfree(data_ptr); if (code) goto out; code = krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16); if (code) goto out; if (signalg == 0) cksum.len = 8; else cksum.len = 16; cksum.data = md5cksum.data + 16 - cksum.len; dprintk ("RPC: krb5_read_token: memcmp digest cksum.len %d:\n", cksum.len); dprintk(" md5cksum.data\n"); print_hexl((u32 *) md5cksum.data, 16, 0); dprintk(" cksum.data:\n"); print_hexl((u32 *) cksum.data, cksum.len, 0); { u32 *p; (u8 *) p = ptr + 14; dprintk(" ptr+14:\n"); print_hexl(p, cksum.len, 0); } code = memcmp(cksum.data, ptr + 14, cksum.len); break; default: ret = GSS_S_DEFECTIVE_TOKEN; goto out; } ret = GSS_S_BAD_SIG; if (code) goto out; /* it got through unscathed. Make sure the context is unexpired */ if (toktype == KG_TOK_WRAP_MSG) *message_buffer = token; if (qop_state) *qop_state = GSS_C_QOP_DEFAULT; now = jiffies; ret = GSS_S_CONTEXT_EXPIRED; if (now > ctx->endtime) goto out; /* do sequencing checks */ ret = GSS_S_BAD_SIG; if ((code = krb5_get_seq_num(ctx->seq, ptr + 14, ptr + 6, &direction, &seqnum))) goto out; if ((ctx->initiate && direction != 0xff) || (!ctx->initiate && direction != 0)) goto out; ret = GSS_S_COMPLETE; out: if (md5cksum.data) kfree(md5cksum.data); if (toktype == KG_TOK_WRAP_MSG) { if (plain) kfree(plain); if (ret && token.data) kfree(token.data); } return ret; }
int ksm_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms) { krb5_auth_context auth_context = NULL; krb5_error_code retcode; krb5_ccache cc = NULL; int retval = SNMPERR_SUCCESS; krb5_data outdata, ivector; krb5_keyblock *subkey = NULL; #ifdef MIT_NEW_CRYPTO krb5_data input; krb5_enc_data output; unsigned int numcksumtypes; krb5_cksumtype *cksumtype_array; #else /* MIT_NEW_CRYPTO */ krb5_encrypt_block eblock; #endif /* MIT_NEW_CRYPTO */ size_t blocksize, encrypted_length; unsigned char *encrypted_data = NULL; int zero = 0, i; u_char *cksum_pointer, *endp = *parms->wholeMsg; krb5_cksumtype cksumtype; krb5_checksum pdu_checksum; u_char **wholeMsg = parms->wholeMsg; size_t *offset = parms->wholeMsgOffset, seq_offset; struct ksm_secStateRef *ksm_state = (struct ksm_secStateRef *) parms->secStateRef; int rc; DEBUGMSGTL(("ksm", "Starting KSM processing\n")); outdata.length = 0; outdata.data = NULL; ivector.length = 0; ivector.data = NULL; pdu_checksum.contents = NULL; if (!ksm_state) { /* * If we don't have a ksm_state, then we're a request. Get a * credential cache and build a ap_req. */ retcode = krb5_cc_default(kcontext, &cc); if (retcode) { DEBUGMSGTL(("ksm", "KSM: krb5_cc_default failed: %s\n", error_message(retcode))); snmp_set_detail(error_message(retcode)); retval = SNMPERR_KRB5; goto error; } DEBUGMSGTL(("ksm", "KSM: Set credential cache successfully\n")); /* * This seems odd, since we don't need this until later (or earlier, * depending on how you look at it), but because the most likely * errors are Kerberos at this point, I'll get this now to save * time not encoding the rest of the packet. * * Also, we need the subkey to encrypt the PDU (if required). */ retcode = krb5_mk_req(kcontext, &auth_context, AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY, (char *) service_name, parms->session->peername, NULL, cc, &outdata); if (retcode) { DEBUGMSGTL(("ksm", "KSM: krb5_mk_req failed: %s\n", error_message(retcode))); snmp_set_detail(error_message(retcode)); retval = SNMPERR_KRB5; goto error; } DEBUGMSGTL(("ksm", "KSM: ticket retrieved successfully for \"%s/%s\" " "(may not be actual ticket sname)\n", service_name, parms->session->peername)); } else { /* * Grab the auth_context from our security state reference */ auth_context = ksm_state->auth_context; /* * Bundle up an AP_REP. Note that we do this only when we * have a security state reference (which means we're in an agent * and we're sending a response). */ DEBUGMSGTL(("ksm", "KSM: Starting reply processing.\n")); retcode = krb5_mk_rep(kcontext, auth_context, &outdata); if (retcode) { DEBUGMSGTL(("ksm", "KSM: krb5_mk_rep failed: %s\n", error_message(retcode))); snmp_set_detail(error_message(retcode)); retval = SNMPERR_KRB5; goto error; } DEBUGMSGTL(("ksm", "KSM: Finished with krb5_mk_rep()\n")); } /* * If we have to encrypt the PDU, do that now */ if (parms->secLevel == SNMP_SEC_LEVEL_AUTHPRIV) { DEBUGMSGTL(("ksm", "KSM: Starting PDU encryption.\n")); /* * It's weird - * * If we're on the manager, it's a local subkey (because that's in * our AP_REQ) * * If we're on the agent, it's a remote subkey (because that comes * FROM the received AP_REQ). */ if (ksm_state) retcode = krb5_auth_con_getremotesubkey(kcontext, auth_context, &subkey); else retcode = krb5_auth_con_getlocalsubkey(kcontext, auth_context, &subkey); if (retcode) { DEBUGMSGTL(("ksm", "KSM: krb5_auth_con_getlocalsubkey failed: %s\n", error_message(retcode))); snmp_set_detail(error_message(retcode)); retval = SNMPERR_KRB5; goto error; } /* * Note that here we need to handle different things between the * old and new crypto APIs. First, we need to get the final encrypted * length of the PDU. */ #ifdef MIT_NEW_CRYPTO retcode = krb5_c_encrypt_length(kcontext, subkey->enctype, parms->scopedPduLen, &encrypted_length); if (retcode) { DEBUGMSGTL(("ksm", "Encryption length calculation failed: %s\n", error_message(retcode))); snmp_set_detail(error_message(retcode)); retval = SNMPERR_KRB5; goto error; } #else /* MIT_NEW_CRYPTO */ krb5_use_enctype(kcontext, &eblock, subkey->enctype); retcode = krb5_process_key(kcontext, &eblock, subkey); if (retcode) { DEBUGMSGTL(("ksm", "krb5_process_key failed: %s\n", error_message(retcode))); snmp_set_detail(error_message(retcode)); retval = SNMPERR_KRB5; goto error; } encrypted_length = krb5_encrypt_size(parms->scopedPduLen, eblock.crypto_entry); #endif /* MIT_NEW_CRYPTO */ encrypted_data = malloc(encrypted_length); if (!encrypted_data) { DEBUGMSGTL(("ksm", "KSM: Unable to malloc %d bytes for encrypt " "buffer: %s\n", parms->scopedPduLen, strerror(errno))); retval = SNMPERR_MALLOC; #ifndef MIT_NEW_CRYPTO krb5_finish_key(kcontext, &eblock); #endif /* ! MIT_NEW_CRYPTO */ goto error; } /* * We need to set up a blank initialization vector for the encryption. * Use a block of all zero's (which is dependent on the block size * of the encryption method). */ #ifdef MIT_NEW_CRYPTO retcode = krb5_c_block_size(kcontext, subkey->enctype, &blocksize); if (retcode) { DEBUGMSGTL(("ksm", "Unable to determine crypto block size: %s\n", error_message(retcode))); snmp_set_detail(error_message(retcode)); retval = SNMPERR_KRB5; goto error; } #else /* MIT_NEW_CRYPTO */ blocksize = krb5_enctype_array[subkey->enctype]->system->block_length; #endif /* MIT_NEW_CRYPTO */ ivector.data = malloc(blocksize); if (!ivector.data) { DEBUGMSGTL(("ksm", "Unable to allocate %d bytes for ivector\n", blocksize)); retval = SNMPERR_MALLOC; goto error; } ivector.length = blocksize; memset(ivector.data, 0, blocksize); /* * Finally! Do the encryption! */ #ifdef MIT_NEW_CRYPTO input.data = (char *) parms->scopedPdu; input.length = parms->scopedPduLen; output.ciphertext.data = (char *) encrypted_data; output.ciphertext.length = encrypted_length; retcode = krb5_c_encrypt(kcontext, subkey, KSM_KEY_USAGE_ENCRYPTION, &ivector, &input, &output); #else /* MIT_NEW_CRYPTO */ retcode = krb5_encrypt(kcontext, (krb5_pointer) parms->scopedPdu, (krb5_pointer) encrypted_data, parms->scopedPduLen, &eblock, ivector.data); krb5_finish_key(kcontext, &eblock); #endif /* MIT_NEW_CRYPTO */ if (retcode) { DEBUGMSGTL(("ksm", "KSM: krb5_encrypt failed: %s\n", error_message(retcode))); retval = SNMPERR_KRB5; snmp_set_detail(error_message(retcode)); goto error; } *offset = 0; rc = asn_realloc_rbuild_string(wholeMsg, parms->wholeMsgLen, offset, 1, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), encrypted_data, encrypted_length); if (rc == 0) { DEBUGMSGTL(("ksm", "Building encrypted payload failed.\n")); retval = SNMPERR_TOO_LONG; goto error; } DEBUGMSGTL(("ksm", "KSM: Encryption complete.\n")); } else { /* * Plaintext PDU (not encrypted) */ if (*parms->wholeMsgLen < parms->scopedPduLen) { DEBUGMSGTL(("ksm", "Not enough room for plaintext PDU.\n")); retval = SNMPERR_TOO_LONG; goto error; } } /* * Start encoding the msgSecurityParameters * * For now, use 0 for the response hint */ DEBUGMSGTL(("ksm", "KSM: scopedPdu added to payload\n")); seq_offset = *offset; rc = asn_realloc_rbuild_int(wholeMsg, parms->wholeMsgLen, offset, 1, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), (long *) &zero, sizeof(zero)); if (rc == 0) { DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n")); retval = SNMPERR_TOO_LONG; goto error; } rc = asn_realloc_rbuild_string(wholeMsg, parms->wholeMsgLen, offset, 1, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), (u_char *) outdata.data, outdata.length); if (rc == 0) { DEBUGMSGTL(("ksm", "Building ksm AP_REQ failed.\n")); retval = SNMPERR_TOO_LONG; goto error; } /* * Now, we need to pick the "right" checksum algorithm. For old * crypto, just pick CKSUMTYPE_RSA_MD5_DES; for new crypto, pick * one of the "approved" ones. */ #ifdef MIT_NEW_CRYPTO retcode = krb5_c_keyed_checksum_types(kcontext, subkey->enctype, &numcksumtypes, &cksumtype_array); if (retcode) { DEBUGMSGTL(("ksm", "Unable to find appropriate keyed checksum: %s\n", error_message(retcode))); snmp_set_detail(error_message(retcode)); retval = SNMPERR_KRB5; goto error; } if (numcksumtypes <= 0) { DEBUGMSGTL(("ksm", "We received a list of zero cksumtypes for this " "enctype (%d)\n", subkey->enctype)); snmp_set_detail("No valid checksum type for this encryption type"); retval = SNMPERR_KRB5; goto error; } /* * It's not clear to me from the API which checksum you're supposed * to support, so I'm taking a guess at the first one */ cksumtype = cksumtype_array[0]; krb5_free_cksumtypes(kcontext, cksumtype_array); DEBUGMSGTL(("ksm", "KSM: Choosing checksum type of %d (subkey type " "of %d)\n", cksumtype, subkey->enctype)); retcode = krb5_c_checksum_length(kcontext, cksumtype, &blocksize); if (retcode) { DEBUGMSGTL(("ksm", "Unable to determine checksum length: %s\n", error_message(retcode))); snmp_set_detail(error_message(retcode)); retval = SNMPERR_KRB5; goto error; } pdu_checksum.length = blocksize; #else /* MIT_NEW_CRYPTO */ if (ksm_state) cksumtype = ksm_state->cksumtype; else cksumtype = CKSUMTYPE_RSA_MD5_DES; if (!is_keyed_cksum(cksumtype)) { DEBUGMSGTL(("ksm", "Checksum type %d is not a keyed checksum\n", cksumtype)); snmp_set_detail("Checksum is not a keyed checksum"); retval = SNMPERR_KRB5; goto error; } if (!is_coll_proof_cksum(cksumtype)) { DEBUGMSGTL(("ksm", "Checksum type %d is not a collision-proof " "checksum\n", cksumtype)); snmp_set_detail("Checksum is not a collision-proof checksum"); retval = SNMPERR_KRB5; goto error; } pdu_checksum.length = krb5_checksum_size(kcontext, cksumtype); pdu_checksum.checksum_type = cksumtype; #endif /* MIT_NEW_CRYPTO */ /* * Note that here, we're just leaving blank space for the checksum; * we remember where that is, and we'll fill it in later. */ *offset += pdu_checksum.length; memset(*wholeMsg + *parms->wholeMsgLen - *offset, 0, pdu_checksum.length); cksum_pointer = *wholeMsg + *parms->wholeMsgLen - *offset; rc = asn_realloc_rbuild_header(wholeMsg, parms->wholeMsgLen, parms->wholeMsgOffset, 1, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), pdu_checksum.length); if (rc == 0) { DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n")); retval = SNMPERR_TOO_LONG; goto error; } rc = asn_realloc_rbuild_int(wholeMsg, parms->wholeMsgLen, parms->wholeMsgOffset, 1, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), (long *) &cksumtype, sizeof(cksumtype)); if (rc == 0) { DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n")); retval = SNMPERR_TOO_LONG; goto error; } rc = asn_realloc_rbuild_sequence(wholeMsg, parms->wholeMsgLen, parms->wholeMsgOffset, 1, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), *offset - seq_offset); if (rc == 0) { DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n")); retval = SNMPERR_TOO_LONG; goto error; } rc = asn_realloc_rbuild_header(wholeMsg, parms->wholeMsgLen, parms->wholeMsgOffset, 1, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), *offset - seq_offset); if (rc == 0) { DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n")); retval = SNMPERR_TOO_LONG; goto error; } DEBUGMSGTL(("ksm", "KSM: Security parameter encoding completed\n")); /* * We're done with the KSM security parameters - now we do the global * header and wrap up the whole PDU. */ if (*parms->wholeMsgLen < parms->globalDataLen) { DEBUGMSGTL(("ksm", "Building global data failed.\n")); retval = SNMPERR_TOO_LONG; goto error; } *offset += parms->globalDataLen; memcpy(*wholeMsg + *parms->wholeMsgLen - *offset, parms->globalData, parms->globalDataLen); rc = asn_realloc_rbuild_sequence(wholeMsg, parms->wholeMsgLen, offset, 1, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), *offset); if (rc == 0) { DEBUGMSGTL(("ksm", "Building master packet sequence.\n")); retval = SNMPERR_TOO_LONG; goto error; } DEBUGMSGTL(("ksm", "KSM: PDU master packet encoding complete.\n")); /* * Now we need to checksum the entire PDU (since it's built). */ pdu_checksum.contents = malloc(pdu_checksum.length); if (!pdu_checksum.contents) { DEBUGMSGTL(("ksm", "Unable to malloc %d bytes for checksum\n", pdu_checksum.length)); retval = SNMPERR_MALLOC; goto error; } /* * If we didn't encrypt the packet, we haven't yet got the subkey. * Get that now. */ if (!subkey) { if (ksm_state) retcode = krb5_auth_con_getremotesubkey(kcontext, auth_context, &subkey); else retcode = krb5_auth_con_getlocalsubkey(kcontext, auth_context, &subkey); if (retcode) { DEBUGMSGTL(("ksm", "krb5_auth_con_getlocalsubkey failed: %s\n", error_message(retcode))); snmp_set_detail(error_message(retcode)); retval = SNMPERR_KRB5; goto error; } } #ifdef MIT_NEW_CRYPTO input.data = (char *) (*wholeMsg + *parms->wholeMsgLen - *offset); input.length = *offset; retcode = krb5_c_make_checksum(kcontext, cksumtype, subkey, KSM_KEY_USAGE_CHECKSUM, &input, &pdu_checksum); #else /* MIT_NEW_CRYPTO */ retcode = krb5_calculate_checksum(kcontext, cksumtype, *wholeMsg + *parms->wholeMsgLen - *offset, *offset, (krb5_pointer) subkey->contents, subkey->length, &pdu_checksum); #endif /* MIT_NEW_CRYPTO */ if (retcode) { DEBUGMSGTL(("ksm", "Calculate checksum failed: %s\n", error_message(retcode))); retval = SNMPERR_KRB5; snmp_set_detail(error_message(retcode)); goto error; } DEBUGMSGTL(("ksm", "KSM: Checksum calculation complete.\n")); memcpy(cksum_pointer, pdu_checksum.contents, pdu_checksum.length); DEBUGMSGTL(("ksm", "KSM: Writing checksum of %d bytes at offset %d\n", pdu_checksum.length, cksum_pointer - (*wholeMsg + 1))); DEBUGMSGTL(("ksm", "KSM: Checksum:")); for (i = 0; i < pdu_checksum.length; i++) DEBUGMSG(("ksm", " %02x", (unsigned int) pdu_checksum.contents[i])); DEBUGMSG(("ksm", "\n")); /* * If we're _not_ called as part of a response (null ksm_state), * then save the auth_context for later using our cache routines. */ if (!ksm_state) { if ((retval = ksm_insert_cache(parms->pdu->msgid, auth_context, (u_char *) parms->secName, parms->secNameLen)) != SNMPERR_SUCCESS) goto error; auth_context = NULL; } DEBUGMSGTL(("ksm", "KSM processing complete!\n")); error: if (pdu_checksum.contents) #ifdef MIT_NEW_CRYPTO krb5_free_checksum_contents(kcontext, &pdu_checksum); #else /* MIT_NEW_CRYPTO */ free(pdu_checksum.contents); #endif /* MIT_NEW_CRYPTO */ if (ivector.data) free(ivector.data); if (subkey) krb5_free_keyblock(kcontext, subkey); if (encrypted_data) free(encrypted_data); if (cc) krb5_cc_close(kcontext, cc); if (auth_context && !ksm_state) krb5_auth_con_free(kcontext, auth_context); return retval; }
int main(int argc, char **argv) { int log_level = 0; char *ap_req_str = NULL; char *plain_text_str; unsigned char *plain_text; size_t plain_text_len; /* krb5 */ krb5_error_code ret; krb5_context context; krb5_auth_context auth_context; char *princ_str_tn = "kink/tn.example.com"; krb5_principal princ_tn; char *princ_str_nut = "kink/nut.example.com"; krb5_principal princ_nut; char *princ_str_krbtgt = "krbtgt/EXAMPLE.COM"; krb5_principal princ_krbtgt; krb5_ccache ccache; krb5_keytab keytab; krb5_creds creds_tgt; krb5_data ap_req; krb5_data cipher_text; prog = (const char *) basename(argv[0]); if (prog == NULL) { fprintf(stderr, "basename: %s -- %s\n", strerror(errno), argv[0]); return(0); /* NOTREACHED */ } { int ch = 0; while ((ch = getopt(argc, argv, "dq:")) != -1) { switch (ch) { case 'd': log_level++; break; case 'q': ap_req_str = optarg; break; default: usage(); /* NOTREACHED */ break; } } argc -= optind; argv += optind; } if (!argc) { usage(); /* NOTREACHED */ } plain_text_str = argv[0]; { printf("DBG: %s starts arg(%s)\n", prog, plain_text_str); } /* prepare encrypted data */ { { /* stdout */ printf("std:plain_text:%s\n", plain_text_str); } plain_text_len = strlen(plain_text_str); plain_text_len = plain_text_len/2 + plain_text_len%2; plain_text = (unsigned char *)malloc(plain_text_len); memset(plain_text, 0, plain_text_len); plain_text = hex2data(plain_text_str, plain_text); } if (ap_req_str != NULL) { hex2krb5data(ap_req_str, &ap_req); if (log_level) { dump_krb5_data(&ap_req); } { /* stdout */ int i = 0; unsigned char *p; p = (unsigned char *)ap_req.data; printf("std:ap_req:"); for (i = 0; i < ap_req.length; i++) { printf("%02x", *p++); } printf("\n"); } } /* prepare krb5 */ { /** init context */ ret = krb5_init_context(&context); if (ret != 0) { printf("ERR:krb5_init_context:%s\n", krb5_get_err_text(context, ret)); return(ret); } /** setup principals */ ret = krb5_parse_name(context, princ_str_tn, &princ_tn); if (ret != 0) { printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_parse_name(context, princ_str_nut, &princ_nut); if (ret != 0) { printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_parse_name(context, princ_str_krbtgt, &princ_krbtgt); if (ret != 0) { printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret)); return(ret); } /** prepare credential cache */ ret = krb5_cc_default(context, &ccache); if (ret != 0) { printf("ERR:krb5_cc_default:%s\n", krb5_get_err_text(context, ret)); return(ret); } /** prepare keytab */ /*ret = krb5_kt_resolve(context, "/usr/local/var/krb5kdc/kadm5.keytab", &keytab);*/ ret = krb5_kt_default(context, &keytab); if (ret != 0) { /* printf("ERR:krb5_kt_default:%s", krb5_get_err_text(context, ret)); */ printf("ERR:krb5_kt_resolve:%s", krb5_get_err_text(context, ret)); return(ret); } } /* get TGT */ /* just only retrieve TGT from credential cache */ { krb5_creds mcreds; memset(&mcreds, 0, sizeof(mcreds)); mcreds.client = princ_tn; mcreds.server = princ_krbtgt; ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcreds, &creds_tgt); if (ret != 0) { printf("ERR:krb5_cc_retrieve_cred:%s\n", krb5_get_err_text(context, ret)); return(ret); } } /* prepare authentiation context */ { ret = krb5_auth_con_init(context, &auth_context); if (ret != 0) { printf("ERR:krb5_auth_con_init:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_auth_con_setflags(context, auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE); if (ret != 0) { printf("ERR:krb5_auth_con_setflags:%s\n", krb5_get_err_text(context, ret)); return(ret); } /* if USE_SKEY */ /* ret = krb5_auth_con_setuserkey(context, auth_context, &creds_tgt.session); if (ret != 0) { printf("ERR:krb5_auth_con_setuseruserkey:%s\n", krb5_get_err_text(context, ret)); return(ret); } */ } /* set keyblock in auth_context */ if (ap_req_str != NULL) { krb5_ticket *ticket; krb5_flags ap_req_options; ap_req_options = AP_OPTS_MUTUAL_REQUIRED; ticket = NULL; ret = krb5_rd_req(context, &auth_context, &ap_req, NULL, keytab, &ap_req_options, &ticket); if (log_level) { printf("info: ticket.ticket.key is SKEYID_d\n"); /*dump_krb5_ticket(context, *ticket);*/ } if (log_level) { printf("ap_req_opt (%d)\n", ap_req_options); } if (ret != 0) { printf("ERR:krb5_rd_req:%s\n", krb5_get_err_text(context, ret)); return(ret); } if (log_level) { dump_krb5_keyblock(auth_context->keyblock); } krb5_free_ticket(context, ticket); } else { krb5_creds mcreds; krb5_creds *cred; krb5_creds cred_copy; memset(&mcreds, 0, sizeof(mcreds)); mcreds.client = princ_tn; mcreds.server = princ_nut; ret = krb5_get_credentials(context, KRB5_GC_CACHED, ccache, &mcreds, &cred); if (ret != 0) { printf("ERR:krb5_get_credentials:%s\n", krb5_get_err_text(context, ret)); return(ret); } /* mk_req_extends reallocate cred, so use a copy */ ret = krb5_copy_creds_contents(context, (const krb5_creds *)cred, &cred_copy); if (ret != 0) { printf("ERR:krb5_copy_creds_contents:%s\n", krb5_get_err_text(context, ret)); return(ret); } /* * If auth_con == NULL, one is allocated. * This is used later. (keyblock is used to decrypt AP_REP) */ ret = krb5_mk_req_extended(context, &auth_context, AP_OPTS_MUTUAL_REQUIRED, NULL /* in_data */, &cred_copy, &ap_req); if (ret != 0) { printf("ERR:krb5_mk_req_extended:%s\n", krb5_get_err_text(context, ret)); return(ret); } } /* encrypt */ { krb5_crypto crypto; ret = krb5_crypto_init(context, auth_context->keyblock, auth_context->keyblock->keytype, &crypto); if (ret != 0) { printf("ERR:krb5_crypto_init:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_encrypt(context, crypto, 39, /* usage */ plain_text, plain_text_len, &cipher_text); if (ret != 0) { printf("ERR:krb5_encrypt:%s\n", krb5_get_err_text(context, ret)); return(ret); } { /* stdout */ int i = 0; unsigned char *p; p = (unsigned char *)cipher_text.data; printf("std:cipher_text:"); for (i = 0; i < cipher_text.length; i++) { printf("%02x", *p++); } printf("\n"); } krb5_crypto_destroy(context, crypto); } /* clenaup */ { /*free(plain_text);*/ /*krb5_data_free(&ap_req);*/ krb5_free_cred_contents(context, &creds_tgt); ret = krb5_kt_close(context, keytab); if (ret != 0) { printf("ERR:krb5_kt_close:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_cc_close(context, ccache); if (ret != 0) { printf("ERR:krb5_cc_close:%s\n", krb5_get_err_text(context, ret)); return(ret); } krb5_free_principal(context, princ_krbtgt); krb5_free_principal(context, princ_nut); krb5_free_principal(context, princ_tn); krb5_free_context(context); } return(0); }