1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright IBM Corp. 2019 4 */ 5 #include <linux/pgtable.h> 6 #include <asm/physmem_info.h> 7 #include <asm/cpacf.h> 8 #include <asm/timex.h> 9 #include <asm/sclp.h> 10 #include <asm/kasan.h> 11 #include "decompressor.h" 12 #include "boot.h" 13 14 #define PRNG_MODE_TDES 1 15 #define PRNG_MODE_SHA512 2 16 #define PRNG_MODE_TRNG 3 17 18 struct prno_parm { 19 u32 res; 20 u32 reseed_counter; 21 u64 stream_bytes; 22 u8 V[112]; 23 u8 C[112]; 24 }; 25 26 struct prng_parm { 27 u8 parm_block[32]; 28 u32 reseed_counter; 29 u64 byte_counter; 30 }; 31 32 static int check_prng(void) 33 { 34 if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG)) { 35 sclp_early_printk("KASLR disabled: CPU has no PRNG\n"); 36 return 0; 37 } 38 if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG)) 39 return PRNG_MODE_TRNG; 40 if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN)) 41 return PRNG_MODE_SHA512; 42 else 43 return PRNG_MODE_TDES; 44 } 45 46 int get_random(unsigned long limit, unsigned long *value) 47 { 48 struct prng_parm prng = { 49 /* initial parameter block for tdes mode, copied from libica */ 50 .parm_block = { 51 0x0F, 0x2B, 0x8E, 0x63, 0x8C, 0x8E, 0xD2, 0x52, 52 0x64, 0xB7, 0xA0, 0x7B, 0x75, 0x28, 0xB8, 0xF4, 53 0x75, 0x5F, 0xD2, 0xA6, 0x8D, 0x97, 0x11, 0xFF, 54 0x49, 0xD8, 0x23, 0xF3, 0x7E, 0x21, 0xEC, 0xA0 55 }, 56 }; 57 unsigned long seed, random; 58 struct prno_parm prno; 59 __u64 entropy[4]; 60 int mode, i; 61 62 mode = check_prng(); 63 seed = get_tod_clock_fast(); 64 switch (mode) { 65 case PRNG_MODE_TRNG: 66 cpacf_trng(NULL, 0, (u8 *) &random, sizeof(random)); 67 break; 68 case PRNG_MODE_SHA512: 69 cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED, &prno, NULL, 0, 70 (u8 *) &seed, sizeof(seed)); 71 cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, &prno, (u8 *) &random, 72 sizeof(random), NULL, 0); 73 break; 74 case PRNG_MODE_TDES: 75 /* add entropy */ 76 *(unsigned long *) prng.parm_block ^= seed; 77 for (i = 0; i < 16; i++) { 78 cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block, 79 (u8 *) entropy, (u8 *) entropy, 80 sizeof(entropy)); 81 memcpy(prng.parm_block, entropy, sizeof(entropy)); 82 } 83 random = seed; 84 cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block, (u8 *) &random, 85 (u8 *) &random, sizeof(random)); 86 break; 87 default: 88 return -1; 89 } 90 *value = random % limit; 91 return 0; 92 } 93 94 static void sort_reserved_ranges(struct reserved_range *res, unsigned long size) 95 { 96 struct reserved_range tmp; 97 int i, j; 98 99 for (i = 1; i < size; i++) { 100 tmp = res[i]; 101 for (j = i - 1; j >= 0 && res[j].start > tmp.start; j--) 102 res[j + 1] = res[j]; 103 res[j + 1] = tmp; 104 } 105 } 106 107 static unsigned long iterate_valid_positions(unsigned long size, unsigned long align, 108 unsigned long _min, unsigned long _max, 109 struct reserved_range *res, size_t res_count, 110 bool pos_count, unsigned long find_pos) 111 { 112 unsigned long start, end, tmp_end, range_pos, pos = 0; 113 struct reserved_range *res_end = res + res_count; 114 struct reserved_range *skip_res; 115 int i; 116 117 align = max(align, 8UL); 118 _min = round_up(_min, align); 119 for_each_physmem_usable_range(i, &start, &end) { 120 if (_min >= end) 121 continue; 122 start = round_up(start, align); 123 if (start >= _max) 124 break; 125 start = max(_min, start); 126 end = min(_max, end); 127 128 while (start + size <= end) { 129 /* skip reserved ranges below the start */ 130 while (res && res->end <= start) { 131 res++; 132 if (res >= res_end) 133 res = NULL; 134 } 135 skip_res = NULL; 136 tmp_end = end; 137 /* has intersecting reserved range */ 138 if (res && res->start < end) { 139 skip_res = res; 140 tmp_end = res->start; 141 } 142 if (start + size <= tmp_end) { 143 range_pos = (tmp_end - start - size) / align + 1; 144 if (pos_count) { 145 pos += range_pos; 146 } else { 147 if (range_pos >= find_pos) 148 return start + (find_pos - 1) * align; 149 find_pos -= range_pos; 150 } 151 } 152 if (!skip_res) 153 break; 154 start = round_up(skip_res->end, align); 155 } 156 } 157 158 return pos_count ? pos : 0; 159 } 160 161 /* 162 * Two types of decompressor memory allocations/reserves are considered 163 * differently. 164 * 165 * "Static" or "single" allocations are done via physmem_alloc_range() and 166 * physmem_reserve(), and they are listed in physmem_info.reserved[]. Each 167 * type of "static" allocation can only have one allocation per type and 168 * cannot have chains. 169 * 170 * On the other hand, "dynamic" or "repetitive" allocations are done via 171 * physmem_alloc_top_down(). These allocations are tightly packed together 172 * top down from the end of online memory. physmem_alloc_pos represents 173 * current position where those allocations start. 174 * 175 * Functions randomize_within_range() and iterate_valid_positions() 176 * only consider "dynamic" allocations by never looking above 177 * physmem_alloc_pos. "Static" allocations, however, are explicitly 178 * considered by checking the "res" (reserves) array. The first 179 * reserved_range of a "dynamic" allocation may also be checked along the 180 * way, but it will always be above the maximum value anyway. 181 */ 182 unsigned long randomize_within_range(unsigned long size, unsigned long align, 183 unsigned long min, unsigned long max) 184 { 185 struct reserved_range res[RR_MAX]; 186 unsigned long max_pos, pos; 187 188 memcpy(res, physmem_info.reserved, sizeof(res)); 189 sort_reserved_ranges(res, ARRAY_SIZE(res)); 190 max = min(max, get_physmem_alloc_pos()); 191 192 max_pos = iterate_valid_positions(size, align, min, max, res, ARRAY_SIZE(res), true, 0); 193 if (!max_pos) 194 return 0; 195 if (get_random(max_pos, &pos)) 196 return 0; 197 return iterate_valid_positions(size, align, min, max, res, ARRAY_SIZE(res), false, pos + 1); 198 } 199
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.