krb5_error_code krb5_encrypt_tkt_part(krb5_context context, const krb5_keyblock *key, krb5_ticket *ticket) { krb5_data *data = 0; int code; size_t enclen; if ((code = encode_krb5_enc_tkt_part(ticket->enc_part2, &data))) goto Done; if ((code = krb5_c_encrypt_length(context, key->enctype, data->length, &enclen))) goto Done; ticket->enc_part.ciphertext.length = enclen; if (!(ticket->enc_part.ciphertext.data = malloc(enclen))) { code = ENOMEM; goto Done; } if ((code = krb5_c_encrypt(context, key, KRB5_KEYUSAGE_KDC_REP_TICKET, 0, data, &ticket->enc_part))) { free(ticket->enc_part.ciphertext.data); ticket->enc_part.ciphertext.data = 0; } Done: if (data) { if (data->data) free(data->data); free(data); } return code; }
krb5_error_code krb5_encrypt_tkt_part(krb5_context context, const krb5_keyblock *srv_key, krb5_ticket *dec_ticket) { krb5_data *scratch; krb5_error_code retval; krb5_enc_tkt_part *dec_tkt_part = dec_ticket->enc_part2; /* start by encoding the to-be-encrypted part. */ if ((retval = encode_krb5_enc_tkt_part(dec_tkt_part, &scratch))) { return retval; } #define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \ krb5_free_data(context, scratch); } /* call the encryption routine */ retval = krb5_encrypt_helper(context, srv_key, KRB5_KEYUSAGE_KDC_REP_TICKET, scratch, &dec_ticket->enc_part); cleanup_scratch(); return(retval); }
/* Encode enc_tkt with contents as the authdata field, for use in KDC * verifier checksums. */ static krb5_error_code encode_kdcver_encpart(krb5_enc_tkt_part *enc_tkt, krb5_authdata **contents, krb5_data **der_out) { krb5_enc_tkt_part ck_enctkt; ck_enctkt = *enc_tkt; ck_enctkt.authorization_data = contents; return encode_krb5_enc_tkt_part(&ck_enctkt, der_out); }
/* * AIX krb5 has krb5_decrypt_tkt_part, but no krb5_c_decrypt. So, implement our * own krb5_c_decrypt. Note that this krb5_c_decrypt is only suitable for * decrypting an encrypted krb5_enc_tkt_part. But since that's all we ever use * it for, that should be fine. */ static krb5_error_code krb5_c_decrypt(krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *cipher_state, const krb5_enc_data *input, krb5_data *output) { krb5_ticket tkt; krb5_error_code code; krb5_data *tout = NULL; /* We only handle a subset of possible arguments; if we somehow get passed * something else, bail out with EINVAL. */ if (cipher_state != NULL) return EINVAL; if (usage != KRB5_KEYUSAGE_KDC_REP_TICKET) return EINVAL; memset(&tkt, 0, sizeof(tkt)); tkt.enc_part = *input; code = krb5_decrypt_tkt_part(context, key, &tkt); if (code != 0) return code; code = encode_krb5_enc_tkt_part(tkt.enc_part2, &tout); if (code != 0) return code; if (tout->length > output->length) { /* This should never happen, but don't assert since we may be dealing * with untrusted user data. */ code = EINVAL; goto error; } memcpy(output->data, tout->data, tout->length); output->length = tout->length; error: if (tout) krb5_free_data(context, tout); return code; }