cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

asn1.c (5610B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
      4 * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
      5 *
      6 * Copyright (c) 2000 RP Internet (www.rpi.net.au).
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/types.h>
     11#include <linux/kernel.h>
     12#include <linux/mm.h>
     13#include <linux/slab.h>
     14#include <linux/oid_registry.h>
     15
     16#include "glob.h"
     17
     18#include "asn1.h"
     19#include "connection.h"
     20#include "auth.h"
     21#include "ksmbd_spnego_negtokeninit.asn1.h"
     22#include "ksmbd_spnego_negtokentarg.asn1.h"
     23
     24#define NTLMSSP_OID_LEN  10
     25
     26static char NTLMSSP_OID_STR[NTLMSSP_OID_LEN] = { 0x2b, 0x06, 0x01, 0x04, 0x01,
     27	0x82, 0x37, 0x02, 0x02, 0x0a };
     28
     29int
     30ksmbd_decode_negTokenInit(unsigned char *security_blob, int length,
     31			  struct ksmbd_conn *conn)
     32{
     33	return asn1_ber_decoder(&ksmbd_spnego_negtokeninit_decoder, conn,
     34				security_blob, length);
     35}
     36
     37int
     38ksmbd_decode_negTokenTarg(unsigned char *security_blob, int length,
     39			  struct ksmbd_conn *conn)
     40{
     41	return asn1_ber_decoder(&ksmbd_spnego_negtokentarg_decoder, conn,
     42				security_blob, length);
     43}
     44
     45static int compute_asn_hdr_len_bytes(int len)
     46{
     47	if (len > 0xFFFFFF)
     48		return 4;
     49	else if (len > 0xFFFF)
     50		return 3;
     51	else if (len > 0xFF)
     52		return 2;
     53	else if (len > 0x7F)
     54		return 1;
     55	else
     56		return 0;
     57}
     58
     59static void encode_asn_tag(char *buf, unsigned int *ofs, char tag, char seq,
     60			   int length)
     61{
     62	int i;
     63	int index = *ofs;
     64	char hdr_len = compute_asn_hdr_len_bytes(length);
     65	int len = length + 2 + hdr_len;
     66
     67	/* insert tag */
     68	buf[index++] = tag;
     69
     70	if (!hdr_len) {
     71		buf[index++] = len;
     72	} else {
     73		buf[index++] = 0x80 | hdr_len;
     74		for (i = hdr_len - 1; i >= 0; i--)
     75			buf[index++] = (len >> (i * 8)) & 0xFF;
     76	}
     77
     78	/* insert seq */
     79	len = len - (index - *ofs);
     80	buf[index++] = seq;
     81
     82	if (!hdr_len) {
     83		buf[index++] = len;
     84	} else {
     85		buf[index++] = 0x80 | hdr_len;
     86		for (i = hdr_len - 1; i >= 0; i--)
     87			buf[index++] = (len >> (i * 8)) & 0xFF;
     88	}
     89
     90	*ofs += (index - *ofs);
     91}
     92
     93int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer, u16 *buflen,
     94				  char *ntlm_blob, int ntlm_blob_len)
     95{
     96	char *buf;
     97	unsigned int ofs = 0;
     98	int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
     99	int oid_len = 4 + compute_asn_hdr_len_bytes(NTLMSSP_OID_LEN) * 2 +
    100		NTLMSSP_OID_LEN;
    101	int ntlmssp_len = 4 + compute_asn_hdr_len_bytes(ntlm_blob_len) * 2 +
    102		ntlm_blob_len;
    103	int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len +
    104			oid_len + ntlmssp_len) * 2 +
    105			neg_result_len + oid_len + ntlmssp_len;
    106
    107	buf = kmalloc(total_len, GFP_KERNEL);
    108	if (!buf)
    109		return -ENOMEM;
    110
    111	/* insert main gss header */
    112	encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len + oid_len +
    113			ntlmssp_len);
    114
    115	/* insert neg result */
    116	encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
    117	buf[ofs++] = 1;
    118
    119	/* insert oid */
    120	encode_asn_tag(buf, &ofs, 0xa1, 0x06, NTLMSSP_OID_LEN);
    121	memcpy(buf + ofs, NTLMSSP_OID_STR, NTLMSSP_OID_LEN);
    122	ofs += NTLMSSP_OID_LEN;
    123
    124	/* insert response token - ntlmssp blob */
    125	encode_asn_tag(buf, &ofs, 0xa2, 0x04, ntlm_blob_len);
    126	memcpy(buf + ofs, ntlm_blob, ntlm_blob_len);
    127	ofs += ntlm_blob_len;
    128
    129	*pbuffer = buf;
    130	*buflen = total_len;
    131	return 0;
    132}
    133
    134int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
    135				   int neg_result)
    136{
    137	char *buf;
    138	unsigned int ofs = 0;
    139	int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
    140	int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len) * 2 +
    141		neg_result_len;
    142
    143	buf = kmalloc(total_len, GFP_KERNEL);
    144	if (!buf)
    145		return -ENOMEM;
    146
    147	/* insert main gss header */
    148	encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len);
    149
    150	/* insert neg result */
    151	encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
    152	if (neg_result)
    153		buf[ofs++] = 2;
    154	else
    155		buf[ofs++] = 0;
    156
    157	*pbuffer = buf;
    158	*buflen = total_len;
    159	return 0;
    160}
    161
    162int ksmbd_gssapi_this_mech(void *context, size_t hdrlen, unsigned char tag,
    163			   const void *value, size_t vlen)
    164{
    165	enum OID oid;
    166
    167	oid = look_up_OID(value, vlen);
    168	if (oid != OID_spnego) {
    169		char buf[50];
    170
    171		sprint_oid(value, vlen, buf, sizeof(buf));
    172		ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
    173		return -EBADMSG;
    174	}
    175
    176	return 0;
    177}
    178
    179int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen,
    180				   unsigned char tag, const void *value,
    181				   size_t vlen)
    182{
    183	struct ksmbd_conn *conn = context;
    184	enum OID oid;
    185	int mech_type;
    186
    187	oid = look_up_OID(value, vlen);
    188	if (oid == OID_ntlmssp) {
    189		mech_type = KSMBD_AUTH_NTLMSSP;
    190	} else if (oid == OID_mskrb5) {
    191		mech_type = KSMBD_AUTH_MSKRB5;
    192	} else if (oid == OID_krb5) {
    193		mech_type = KSMBD_AUTH_KRB5;
    194	} else if (oid == OID_krb5u2u) {
    195		mech_type = KSMBD_AUTH_KRB5U2U;
    196	} else {
    197		char buf[50];
    198
    199		sprint_oid(value, vlen, buf, sizeof(buf));
    200		ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
    201		return -EBADMSG;
    202	}
    203
    204	conn->auth_mechs |= mech_type;
    205	if (conn->preferred_auth_mech == 0)
    206		conn->preferred_auth_mech = mech_type;
    207
    208	return 0;
    209}
    210
    211int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
    212				    unsigned char tag, const void *value,
    213				    size_t vlen)
    214{
    215	struct ksmbd_conn *conn = context;
    216
    217	conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
    218	if (!conn->mechToken)
    219		return -ENOMEM;
    220
    221	memcpy(conn->mechToken, value, vlen);
    222	conn->mechToken[vlen] = '\0';
    223	return 0;
    224}
    225
    226int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
    227				    unsigned char tag, const void *value,
    228				    size_t vlen)
    229{
    230	struct ksmbd_conn *conn = context;
    231
    232	conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
    233	if (!conn->mechToken)
    234		return -ENOMEM;
    235
    236	memcpy(conn->mechToken, value, vlen);
    237	conn->mechToken[vlen] = '\0';
    238	return 0;
    239}