1// Copyright 2019 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14package procfs 15 16import ( 17 "bufio" 18 "bytes" 19 "fmt" 20 "io" 21 "strings" 22 23 "github.com/prometheus/procfs/internal/util" 24) 25 26// Crypto holds info parsed from /proc/crypto. 27type Crypto struct { 28 Alignmask *uint64 29 Async bool 30 Blocksize *uint64 31 Chunksize *uint64 32 Ctxsize *uint64 33 Digestsize *uint64 34 Driver string 35 Geniv string 36 Internal string 37 Ivsize *uint64 38 Maxauthsize *uint64 39 MaxKeysize *uint64 40 MinKeysize *uint64 41 Module string 42 Name string 43 Priority *int64 44 Refcnt *int64 45 Seedsize *uint64 46 Selftest string 47 Type string 48 Walksize *uint64 49} 50 51// Crypto parses an crypto-file (/proc/crypto) and returns a slice of 52// structs containing the relevant info. More information available here: 53// https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html 54func (fs FS) Crypto() ([]Crypto, error) { 55 path := fs.proc.Path("crypto") 56 b, err := util.ReadFileNoStat(path) 57 if err != nil { 58 return nil, fmt.Errorf("error reading crypto %q: %w", path, err) 59 } 60 61 crypto, err := parseCrypto(bytes.NewReader(b)) 62 if err != nil { 63 return nil, fmt.Errorf("error parsing crypto %q: %w", path, err) 64 } 65 66 return crypto, nil 67} 68 69// parseCrypto parses a /proc/crypto stream into Crypto elements. 70func parseCrypto(r io.Reader) ([]Crypto, error) { 71 var out []Crypto 72 73 s := bufio.NewScanner(r) 74 for s.Scan() { 75 text := s.Text() 76 switch { 77 case strings.HasPrefix(text, "name"): 78 // Each crypto element begins with its name. 79 out = append(out, Crypto{}) 80 case text == "": 81 continue 82 } 83 84 kv := strings.Split(text, ":") 85 if len(kv) != 2 { 86 return nil, fmt.Errorf("malformed crypto line: %q", text) 87 } 88 89 k := strings.TrimSpace(kv[0]) 90 v := strings.TrimSpace(kv[1]) 91 92 // Parse the key/value pair into the currently focused element. 93 c := &out[len(out)-1] 94 if err := c.parseKV(k, v); err != nil { 95 return nil, err 96 } 97 } 98 99 if err := s.Err(); err != nil { 100 return nil, err 101 } 102 103 return out, nil 104} 105 106// parseKV parses a key/value pair into the appropriate field of c. 107func (c *Crypto) parseKV(k, v string) error { 108 vp := util.NewValueParser(v) 109 110 switch k { 111 case "async": 112 // Interpret literal yes as true. 113 c.Async = v == "yes" 114 case "blocksize": 115 c.Blocksize = vp.PUInt64() 116 case "chunksize": 117 c.Chunksize = vp.PUInt64() 118 case "digestsize": 119 c.Digestsize = vp.PUInt64() 120 case "driver": 121 c.Driver = v 122 case "geniv": 123 c.Geniv = v 124 case "internal": 125 c.Internal = v 126 case "ivsize": 127 c.Ivsize = vp.PUInt64() 128 case "maxauthsize": 129 c.Maxauthsize = vp.PUInt64() 130 case "max keysize": 131 c.MaxKeysize = vp.PUInt64() 132 case "min keysize": 133 c.MinKeysize = vp.PUInt64() 134 case "module": 135 c.Module = v 136 case "name": 137 c.Name = v 138 case "priority": 139 c.Priority = vp.PInt64() 140 case "refcnt": 141 c.Refcnt = vp.PInt64() 142 case "seedsize": 143 c.Seedsize = vp.PUInt64() 144 case "selftest": 145 c.Selftest = v 146 case "type": 147 c.Type = v 148 case "walksize": 149 c.Walksize = vp.PUInt64() 150 } 151 152 return vp.Err() 153} 154