runtime: add runtime.rand function
This function is needed for Go 1.22, and is used from various packages like math/rand. When there is no random number generator available, it falls back to a static sequence of numbers. I think this is fine, because as far as I can see it is only used for non-cryptographic needs.
Этот коммит содержится в:
		
							родитель
							
								
									204659bdcd
								
							
						
					
					
						коммит
						e9003e2deb
					
				
					 11 изменённых файлов: 102 добавлений и 1 удалений
				
			
		|  | @ -838,6 +838,7 @@ endif | |||
| 	@cp -rp lib/musl/src/include         build/release/tinygo/lib/musl/src | ||||
| 	@cp -rp lib/musl/src/internal        build/release/tinygo/lib/musl/src | ||||
| 	@cp -rp lib/musl/src/legacy          build/release/tinygo/lib/musl/src | ||||
| 	@cp -rp lib/musl/src/linux           build/release/tinygo/lib/musl/src | ||||
| 	@cp -rp lib/musl/src/malloc          build/release/tinygo/lib/musl/src | ||||
| 	@cp -rp lib/musl/src/mman            build/release/tinygo/lib/musl/src | ||||
| 	@cp -rp lib/musl/src/math            build/release/tinygo/lib/musl/src | ||||
|  |  | |||
|  | @ -119,6 +119,7 @@ var Musl = Library{ | |||
| 			"internal/syscall_ret.c", | ||||
| 			"internal/vdso.c", | ||||
| 			"legacy/*.c", | ||||
| 			"linux/*.c", | ||||
| 			"malloc/*.c", | ||||
| 			"malloc/mallocng/*.c", | ||||
| 			"mman/*.c", | ||||
|  |  | |||
|  | @ -1,4 +1,7 @@ | |||
| //go:build nrf || stm32 || (sam && atsamd51) || (sam && atsame5x) || esp32c3 | ||||
| //go:build nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 | ||||
| 
 | ||||
| // If you update the above build constraint, you'll probably also need to update | ||||
| // src/runtime/rand_hwrng.go. | ||||
| 
 | ||||
| package rand | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,6 +16,8 @@ func rand_fastrand64() uint64 { | |||
| } | ||||
| 
 | ||||
| // This function is used by hash/maphash. | ||||
| // This function isn't required anymore since Go 1.22, so should be removed once | ||||
| // that becomes the minimum requirement. | ||||
| func fastrand() uint32 { | ||||
| 	xorshift32State = xorshift32(xorshift32State) | ||||
| 	return xorshift32State | ||||
|  | @ -34,6 +36,8 @@ func xorshift32(x uint32) uint32 { | |||
| } | ||||
| 
 | ||||
| // This function is used by hash/maphash. | ||||
| // This function isn't required anymore since Go 1.22, so should be removed once | ||||
| // that becomes the minimum requirement. | ||||
| func fastrand64() uint64 { | ||||
| 	xorshift64State = xorshiftMult64(xorshift64State) | ||||
| 	return xorshift64State | ||||
|  | @ -56,3 +60,16 @@ func memhash(p unsafe.Pointer, seed, s uintptr) uintptr { | |||
| 	} | ||||
| 	return uintptr(hash32(p, s, seed)) | ||||
| } | ||||
| 
 | ||||
| // Function that's called from various packages starting with Go 1.22. | ||||
| func rand() uint64 { | ||||
| 	// Return a random number from hardware, falling back to software if | ||||
| 	// unavailable. | ||||
| 	n, ok := hardwareRand() | ||||
| 	if !ok { | ||||
| 		// Fallback to static random number. | ||||
| 		// Not great, but we can't do much better than this. | ||||
| 		n = fastrand64() | ||||
| 	} | ||||
| 	return n | ||||
| } | ||||
|  |  | |||
|  | @ -112,3 +112,14 @@ func findGlobals(found func(start, end uintptr)) { | |||
| 		cmd = (*segmentLoadCommand)(unsafe.Add(unsafe.Pointer(cmd), cmd.cmdsize)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func hardwareRand() (n uint64, ok bool) { | ||||
| 	n |= uint64(libc_arc4random()) | ||||
| 	n |= uint64(libc_arc4random()) << 32 | ||||
| 	return n, true | ||||
| } | ||||
| 
 | ||||
| // uint32_t arc4random(void); | ||||
| // | ||||
| //export arc4random | ||||
| func libc_arc4random() uint32 | ||||
|  |  | |||
|  | @ -120,3 +120,16 @@ func libc_getpagesize() int | |||
| func syscall_Getpagesize() int { | ||||
| 	return libc_getpagesize() | ||||
| } | ||||
| 
 | ||||
| func hardwareRand() (n uint64, ok bool) { | ||||
| 	read := libc_getrandom(unsafe.Pointer(&n), 8, 0) | ||||
| 	if read != 8 { | ||||
| 		return 0, false | ||||
| 	} | ||||
| 	return n, true | ||||
| } | ||||
| 
 | ||||
| // ssize_t getrandom(void buf[.buflen], size_t buflen, unsigned int flags); | ||||
| // | ||||
| //export getrandom | ||||
| func libc_getrandom(buf unsafe.Pointer, buflen uintptr, flags uint32) uint32 | ||||
|  |  | |||
							
								
								
									
										16
									
								
								src/runtime/rand_hwrng.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										16
									
								
								src/runtime/rand_hwrng.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,16 @@ | |||
| //go:build baremetal && (nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3) | ||||
| 
 | ||||
| // If you update the above build constraint, you'll probably also need to update | ||||
| // src/crypto/rand/rand_baremetal.go. | ||||
| 
 | ||||
| package runtime | ||||
| 
 | ||||
| import "machine" | ||||
| 
 | ||||
| func hardwareRand() (n uint64, ok bool) { | ||||
| 	n1, err1 := machine.GetRNG() | ||||
| 	n2, err2 := machine.GetRNG() | ||||
| 	n = uint64(n1)<<32 | uint64(n2) | ||||
| 	ok = err1 == nil && err2 == nil | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										7
									
								
								src/runtime/rand_norng.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										7
									
								
								src/runtime/rand_norng.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,7 @@ | |||
| //go:build baremetal && !(nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3) | ||||
| 
 | ||||
| package runtime | ||||
| 
 | ||||
| func hardwareRand() (n uint64, ok bool) { | ||||
| 	return 0, false // no RNG available | ||||
| } | ||||
|  | @ -308,3 +308,8 @@ func svcOutputDebugString(str *uint8, size uint64) uint64 | |||
| // | ||||
| //export svcGetInfo | ||||
| func svcGetInfo(output *uint64, id0 uint32, handle uint32, id1 uint64) uint64 | ||||
| 
 | ||||
| func hardwareRand() (n uint64, ok bool) { | ||||
| 	// TODO: see whether there is a RNG and use it. | ||||
| 	return 0, false | ||||
| } | ||||
|  |  | |||
|  | @ -85,3 +85,14 @@ func procPin() { | |||
| //go:linkname procUnpin sync/atomic.runtime_procUnpin | ||||
| func procUnpin() { | ||||
| } | ||||
| 
 | ||||
| func hardwareRand() (n uint64, ok bool) { | ||||
| 	n |= uint64(libc_arc4random()) | ||||
| 	n |= uint64(libc_arc4random()) << 32 | ||||
| 	return n, true | ||||
| } | ||||
| 
 | ||||
| // uint32_t arc4random(void); | ||||
| // | ||||
| //export arc4random | ||||
| func libc_arc4random() uint32 | ||||
|  |  | |||
|  | @ -228,3 +228,19 @@ func procPin() { | |||
| //go:linkname procUnpin sync/atomic.runtime_procUnpin | ||||
| func procUnpin() { | ||||
| } | ||||
| 
 | ||||
| func hardwareRand() (n uint64, ok bool) { | ||||
| 	var n1, n2 uint32 | ||||
| 	errCode1 := libc_rand_s(&n1) | ||||
| 	errCode2 := libc_rand_s(&n2) | ||||
| 	n = uint64(n1)<<32 | uint64(n2) | ||||
| 	ok = errCode1 == 0 && errCode2 == 0 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Cryptographically secure random number generator. | ||||
| // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rand-s?view=msvc-170 | ||||
| // errno_t rand_s(unsigned int* randomValue); | ||||
| // | ||||
| //export rand_s | ||||
| func libc_rand_s(randomValue *uint32) int32 | ||||
|  |  | |||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 Ayke van Laethem
						Ayke van Laethem